Commit efb1ff6a7e6b04351a870e98b7577675b157972b
0 parents
Exists in
master
and in
1 other branch
first commit
Showing
45 changed files
with
4515 additions
and
0 deletions
Show diff stats
1 | +++ a/.github/workflows/test.yml | |
... | ... | @@ -0,0 +1,20 @@ |
1 | +--- | |
2 | +name: Test | |
3 | + | |
4 | +on: [push, pull_request] | |
5 | + | |
6 | +jobs: | |
7 | + build: | |
8 | + runs-on: ubuntu-latest | |
9 | + strategy: | |
10 | + matrix: | |
11 | + ruby-version: [2.5, 2.6, 2.7, '3.0', 3.1, 3.2] | |
12 | + name: Ruby ${{ matrix.ruby-version }} | |
13 | + steps: | |
14 | + - uses: actions/checkout@v3 | |
15 | + - name: Setup Ruby | |
16 | + uses: ruby/setup-ruby@v1 | |
17 | + with: | |
18 | + ruby-version: ${{ matrix.ruby-version }} | |
19 | + - run: bundle install | |
20 | + - run: bundle exec rake | ... | ... |
1 | +++ a/.rubocop.yml | |
... | ... | @@ -0,0 +1,56 @@ |
1 | +Style/Encoding: | |
2 | + Enabled: false | |
3 | + | |
4 | +Lint/AmbiguousOperator: | |
5 | + Enabled: false | |
6 | + | |
7 | +Layout/CaseIndentation: | |
8 | + Enabled: false | |
9 | + | |
10 | +Metrics/CyclomaticComplexity: | |
11 | + Enabled: false | |
12 | + Max: 10 | |
13 | + | |
14 | +Metrics/PerceivedComplexity: | |
15 | + Enabled: false | |
16 | + Max: 10 | |
17 | + | |
18 | +Style/Documentation: | |
19 | + Enabled: false | |
20 | + | |
21 | +Layout/EmptyLinesAroundBlockBody: | |
22 | + Enabled: false | |
23 | + | |
24 | +Layout/EmptyLinesAroundClassBody: | |
25 | + Enabled: false | |
26 | + | |
27 | +Layout/EmptyLinesAroundModuleBody: | |
28 | + Enabled: false | |
29 | + | |
30 | +Metrics/ClassLength: | |
31 | + Enabled: false | |
32 | + | |
33 | +Style/FrozenStringLiteralComment: | |
34 | + Enabled: false | |
35 | + | |
36 | +Layout/LineLength: | |
37 | + Enabled: true | |
38 | + Max: 160 | |
39 | + | |
40 | +Metrics/MethodLength: | |
41 | + Enabled: false | |
42 | + | |
43 | +Style/ModuleFunction: | |
44 | + Enabled: false | |
45 | + | |
46 | +Style/NestedTernaryOperator: | |
47 | + Enabled: false | |
48 | + | |
49 | +Style/RaiseArgs: | |
50 | + Enabled: false | |
51 | + | |
52 | +Style/RescueModifier: | |
53 | + Enabled: false | |
54 | + | |
55 | +Lint/UnusedMethodArgument: | |
56 | + Enabled: false | ... | ... |
1 | +++ a/CHANGELOG.md | |
... | ... | @@ -0,0 +1,48 @@ |
1 | +### [0.13.0] - 2023-11-04 | |
2 | +* Fix zero hour | |
3 | + | |
4 | +### [0.12.0] - 2023-04-16 | |
5 | +* Add "strict_quartz" option for Java Quartz implementation (quartz-scheduler) | |
6 | + | |
7 | +### [0.11.1] - 2020-10-21 | |
8 | +* Fix two consecutive commas in interval expressions | |
9 | + | |
10 | +### [0.11.0] - 2020-10-05 | |
11 | +* Fix handling L in day of month expressions | |
12 | + | |
13 | +### [0.10.0] - 2020-05-26 | |
14 | +* Move locale and timezone arguments to options | |
15 | + | |
16 | +### [0.9.2] - 2020-04-24 | |
17 | +* Add italian locale | |
18 | + | |
19 | +### [0.9.1] - 2019-11-26 | |
20 | +* Update tzinfo dependency | |
21 | + | |
22 | +### [0.9.0] - 2019-04-21 | |
23 | +* Add german locale | |
24 | + | |
25 | +### [0.8.0] - 2019-04-18 | |
26 | +* Add support for timezones | |
27 | + | |
28 | +### [0.7.0] - 2018-11-22 | |
29 | +* Include day of week when day of month is specified | |
30 | + | |
31 | +### [0.6.1] - 2017-11-17 | |
32 | +* Fix 4th day spelling | |
33 | + | |
34 | +### [0.6.0] - 2017-02-17 | |
35 | +* Add romanian and russian locales | |
36 | +* Minor fixes to the french locale | |
37 | + | |
38 | +### [0.5.0] - 2017-02-15 | |
39 | +* Add french locale | |
40 | + | |
41 | +### [0.4.0] - 2016-11-28 | |
42 | +* Fix handling leading zeros in numbers | |
43 | + | |
44 | +### [0.3.0] - 2016-03-02 | |
45 | +* Add pt_BR locale | |
46 | + | |
47 | +### [0.2.0] - 2015-10-25 | |
48 | +* Initial public version | ... | ... |
1 | +++ a/LICENSE.md | |
... | ... | @@ -0,0 +1,13 @@ |
1 | +Copyright 2015, Opower | |
2 | + | |
3 | +Licensed under the Apache License, Version 2.0 (the "License"); | |
4 | +you may not use this file except in compliance with the License. | |
5 | +You may obtain a copy of the License at | |
6 | + | |
7 | + http://www.apache.org/licenses/LICENSE-2.0 | |
8 | + | |
9 | +Unless required by applicable law or agreed to in writing, software | |
10 | +distributed under the License is distributed on an "AS IS" BASIS, | |
11 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 | +See the License for the specific language governing permissions and | |
13 | +limitations under the License. | ... | ... |
1 | +++ a/README.md | |
... | ... | @@ -0,0 +1,86 @@ |
1 | +# Cronex | |
2 | + | |
3 | +[](https://badge.fury.io/rb/cronex) | |
4 | +[](https://github.com/alpinweis/cronex/actions/workflows/test.yml?query=branch%3Amaster) | |
5 | + | |
6 | +A Ruby library that converts cron expressions into human readable strings. | |
7 | +Translated to Ruby from [cron-expression-descriptor](https://github.com/bradyholt/cron-expression-descriptor) (C#) via | |
8 | +[cron-parser](https://github.com/RedHogs/cron-parser) (Java). | |
9 | + | |
10 | +Original Author & Credit: Brady Holt (http://www.geekytidbits.com). | |
11 | + | |
12 | +## Features | |
13 | + | |
14 | + * Supports all cron expression special characters including: `*` `/` `,` `-` `?` `L` `W` `#` | |
15 | + * Supports 5, 6 (w/ seconds or year), or 7 (w/ seconds and year) part cron expressions | |
16 | + * Provides casing options (sentence, title, lower) | |
17 | + * Support for non-standard non-zero-based week day numbers | |
18 | + * Supports printing to locale specific human readable format | |
19 | + * Supports displaying times in specific timezones | |
20 | + | |
21 | +For a quick intro to cron see Quartz [Cron Tutorial](http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html). | |
22 | + | |
23 | +## Available Locales | |
24 | + | |
25 | +* English | |
26 | +* Brazilian | |
27 | +* French | |
28 | +* German | |
29 | +* Italian | |
30 | +* Romanian | |
31 | +* Russian | |
32 | + | |
33 | +## Installation | |
34 | + | |
35 | +Add this line to your application's Gemfile: | |
36 | + | |
37 | + gem 'cronex' | |
38 | + | |
39 | +And then execute: | |
40 | + | |
41 | + $ bundle install | |
42 | + | |
43 | +Or install it yourself as: | |
44 | + | |
45 | + $ gem install cronex | |
46 | + | |
47 | +## Usage | |
48 | + | |
49 | +#### Zero based day of week | |
50 | + | |
51 | + Cronex::ExpressionDescriptor.new('*/5 15 * * 1-5').description | |
52 | + => Every 5 minutes, at 3:00 PM, Monday through Friday | |
53 | + | |
54 | + Cronex::ExpressionDescriptor.new('0 0/30 8-9 5,20 * ?').description | |
55 | + => Every 30 minutes, between 8:00 AM and 9:59 AM, on day 5 and 20 of the month | |
56 | + | |
57 | +#### Non-zero based day of week | |
58 | + | |
59 | + Cronex::ExpressionDescriptor.new('*/5 15 * * 1-5', zero_based_dow: false).description | |
60 | + => Every 5 minutes, at 3:00 PM, Sunday through Thursday | |
61 | + | |
62 | +#### Localization | |
63 | + | |
64 | + Cronex::ExpressionDescriptor.new('30 2 * 2 1-5', locale: 'fr').description | |
65 | + => À 2:30 AM, lundi à vendredi, seulement en février | |
66 | + | |
67 | +#### Timezones | |
68 | + | |
69 | + Cronex::ExpressionDescriptor.new('0-10 11 * * *', timezone: 'America/Los_Angeles').description | |
70 | + => Every minute between 4:00 AM and 4:10 AM # PDT or | |
71 | + => Every minute between 3:00 AM and 3:10 AM # PST | |
72 | + | |
73 | +### Strict quartz-scheduler implementation support | |
74 | + | |
75 | + Cronex::ExpressionDescriptor.new('* * * * *', strict_quartz: true).description | |
76 | + => Cronex::ExpressionError (Error: Expression only has 5 parts. For 'strict_quartz' option, at least 6 parts are required) | |
77 | + | |
78 | +See spec tests for more examples. | |
79 | + | |
80 | +### Contributing | |
81 | + | |
82 | +1. Fork it | |
83 | +2. Create your feature branch (`git checkout -b my-new-feature`) | |
84 | +3. Commit your changes (`git commit -am 'Add some feature'`) | |
85 | +4. Push to the branch (`git push origin my-new-feature`) | |
86 | +5. Create new Pull Request | ... | ... |
1 | +++ a/cronex.gemspec | |
... | ... | @@ -0,0 +1,28 @@ |
1 | +# -*- encoding: utf-8 -*- | |
2 | +require File.expand_path('../lib/cronex/version', __FILE__) | |
3 | + | |
4 | +Gem::Specification.new do |spec| | |
5 | + spec.name = 'cronex' | |
6 | + spec.version = Cronex::VERSION | |
7 | + spec.summary = 'Ruby library that converts cron expressions into human readable strings' | |
8 | + spec.description = spec.summary | |
9 | + spec.homepage = 'https://github.com/alpinweis/cronex' | |
10 | + | |
11 | + spec.authors = ['Adrian Kazaku'] | |
12 | + spec.email = ['alpinweis@gmail.com'] | |
13 | + | |
14 | + spec.required_ruby_version = '>= 1.9.3' | |
15 | + | |
16 | + spec.license = 'Apache-2.0' | |
17 | + | |
18 | + spec.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR) | |
19 | + spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) } | |
20 | + spec.test_files = spec.files.grep(/^(test|spec|features)\//) | |
21 | + spec.require_paths = ['lib'] | |
22 | + | |
23 | + spec.add_runtime_dependency 'tzinfo' | |
24 | + spec.add_runtime_dependency 'unicode' | |
25 | + spec.add_development_dependency 'pry', '~> 0.10' | |
26 | + spec.add_development_dependency 'rake', '>= 12.3.3' | |
27 | + spec.add_development_dependency 'rspec', '~> 3.1' | |
28 | +end | ... | ... |
1 | +++ a/lib/cronex.rb | |
... | ... | @@ -0,0 +1,10 @@ |
1 | +require 'date' | |
2 | +require 'time' | |
3 | +require 'yaml' | |
4 | +require_relative 'cronex/version' | |
5 | +require_relative 'cronex/errors' | |
6 | +require_relative 'cronex/resource' | |
7 | +require_relative 'cronex/utils' | |
8 | +require_relative 'cronex/parser' | |
9 | +require_relative 'cronex/exp_descriptor' | |
10 | +require_relative 'cronex/description' | ... | ... |
1 | +++ a/lib/cronex/description.rb | |
... | ... | @@ -0,0 +1,8 @@ |
1 | +require_relative 'description/base' | |
2 | +require_relative 'description/seconds' | |
3 | +require_relative 'description/minutes' | |
4 | +require_relative 'description/hours' | |
5 | +require_relative 'description/day_of_week' | |
6 | +require_relative 'description/day_of_month' | |
7 | +require_relative 'description/month' | |
8 | +require_relative 'description/year' | ... | ... |
1 | +++ a/lib/cronex/description/base.rb | |
... | ... | @@ -0,0 +1,61 @@ |
1 | +module Cronex | |
2 | + class Description | |
3 | + | |
4 | + attr_accessor :resources, :options | |
5 | + | |
6 | + def initialize(resources, options = {}) | |
7 | + @resources = resources | |
8 | + @options = options || {} | |
9 | + end | |
10 | + | |
11 | + def special_chars | |
12 | + ['/', '-', ','] | |
13 | + end | |
14 | + | |
15 | + def segment_description(expression, all_values_description) | |
16 | + if expression.empty? || (expression == '0' && self.class != Cronex::HoursDescription) | |
17 | + desc = '' | |
18 | + elsif expression == '*' | |
19 | + desc = all_values_description | |
20 | + elsif !Cronex::Utils.include_any?(expression, special_chars) | |
21 | + desc = format(description_format(expression), single_item_description(expression)) | |
22 | + elsif expression.include?('/') | |
23 | + segments = expression.split('/') | |
24 | + desc = format(interval_description_format(segments[1]), single_item_description(segments[1])) | |
25 | + # interval contains 'between' piece (e.g. 2-59/3) | |
26 | + if segments[0].include?('-') | |
27 | + between_segment_of_interval = segments[0] | |
28 | + between_segments = between_segment_of_interval.split('-') | |
29 | + between = format( | |
30 | + between_description_format(between_segment_of_interval), | |
31 | + single_item_description(between_segments[0]), | |
32 | + single_item_description(between_segments[1]).gsub(':00', ':59')) | |
33 | + desc += ', ' if !between.start_with?(', ') | |
34 | + desc += between | |
35 | + elsif !Cronex::Utils.include_any?(segments[0], special_chars + ['*']) | |
36 | + desc += ', ' + format(starting_description_format(segments[0]), single_item_description(segments[0])) | |
37 | + end | |
38 | + elsif expression.include?('-') | |
39 | + segments = expression.split('-') | |
40 | + desc = format( | |
41 | + between_description_format(expression), | |
42 | + single_item_description(segments[0]), | |
43 | + single_item_description(segments[1]).gsub(':00', ':59')) | |
44 | + elsif expression.include?(',') | |
45 | + segments = expression.split(',') | |
46 | + segments = segments.map { |s| single_item_description(s) } | |
47 | + desc_content = segments[0...-1].join(', ') + ' ' + resources.get('and') + ' ' + segments.last | |
48 | + desc = format(description_format(expression), desc_content) | |
49 | + end | |
50 | + | |
51 | + desc | |
52 | + end | |
53 | + | |
54 | + def plural(expression, singular, plural) | |
55 | + number = Cronex::Utils.number?(expression) | |
56 | + return plural if number && number > 1 | |
57 | + return plural if expression.include?(',') | |
58 | + singular | |
59 | + end | |
60 | + end | |
61 | +end | ... | ... |
1 | +++ a/lib/cronex/description/day_of_month.rb | |
... | ... | @@ -0,0 +1,23 @@ |
1 | +module Cronex | |
2 | + class DayOfMonthDescription < Description | |
3 | + def single_item_description(expression) | |
4 | + expression == 'L' ? resources.get('last_day') : expression | |
5 | + end | |
6 | + | |
7 | + def interval_description_format(expression) | |
8 | + ', ' + resources.get('every_x') + ' ' + plural(expression, resources.get('day'), resources.get('days')) | |
9 | + end | |
10 | + | |
11 | + def between_description_format(expression) | |
12 | + ', ' + resources.get('between_days_of_the_month') | |
13 | + end | |
14 | + | |
15 | + def description_format(expression) | |
16 | + ', ' + resources.get('on_day_of_the_month') | |
17 | + end | |
18 | + | |
19 | + def starting_description_format(expression) | |
20 | + resources.get('starting') + ' ' + resources.get('on_day_of_the_month') | |
21 | + end | |
22 | + end | |
23 | +end | ... | ... |
1 | +++ a/lib/cronex/description/day_of_week.rb | |
... | ... | @@ -0,0 +1,52 @@ |
1 | +module Cronex | |
2 | + class DayOfWeekDescription < Description | |
3 | + def single_item_description(expression) | |
4 | + exp = expression | |
5 | + if expression.include?('#') | |
6 | + exp = expression.partition('#').first | |
7 | + elsif expression.include?('L') | |
8 | + exp = exp.gsub('L', '') | |
9 | + end | |
10 | + | |
11 | + if Cronex::Utils.number?(exp) | |
12 | + dow_num = Cronex::Utils.integer(exp) | |
13 | + zero_based_dow = options[:zero_based_dow] | |
14 | + invalid_dow = !zero_based_dow && dow_num <= 1 | |
15 | + if invalid_dow || (zero_based_dow && dow_num == 0) | |
16 | + return resources.get(Cronex::Utils.day_of_week_name(0).downcase) # or 7 as in java DateTime().withDayOfWeek(7) for Sunday | |
17 | + elsif !zero_based_dow | |
18 | + dow_num -= 1 | |
19 | + end | |
20 | + return resources.get(Cronex::Utils.day_of_week_name(dow_num).downcase) | |
21 | + else | |
22 | + return Date.parse(exp.capitalize).strftime('%A') | |
23 | + end | |
24 | + end | |
25 | + | |
26 | + def interval_description_format(expression) | |
27 | + format(', ' + resources.get('interval_description_format'), expression) | |
28 | + end | |
29 | + | |
30 | + def between_description_format(expression) | |
31 | + ', ' + resources.get('between_weekday_description_format') | |
32 | + end | |
33 | + | |
34 | + def description_format(expression) | |
35 | + if expression.include?('#') | |
36 | + dow_num = expression.split('#').last | |
37 | + days = Hash[%w(1 2 3 4 5).zip(%w(first second third fourth fifth))] | |
38 | + dow_desc = days[dow_num] | |
39 | + dow_desc = dow_desc ? resources.get(dow_desc) : '' | |
40 | + ', ' + resources.get('on_the_day_of_the_month').gsub(/{{.*}}/, dow_desc) | |
41 | + elsif expression.include?('L') | |
42 | + ', ' + resources.get('on_the_last_of_the_month') | |
43 | + else | |
44 | + ', ' + resources.get('only_on') | |
45 | + end | |
46 | + end | |
47 | + | |
48 | + def starting_description_format(expression) | |
49 | + resources.get('starting') + ' ' + resources.get('on_x') | |
50 | + end | |
51 | + end | |
52 | +end | ... | ... |
1 | +++ a/lib/cronex/description/hours.rb | |
... | ... | @@ -0,0 +1,23 @@ |
1 | +module Cronex | |
2 | + class HoursDescription < Description | |
3 | + def single_item_description(expression, timezone = 'UTC') | |
4 | + Cronex::Utils.format_time(expression, '0', '', timezone) | |
5 | + end | |
6 | + | |
7 | + def interval_description_format(expression) | |
8 | + format(resources.get('every_x') + ' ' + plural(expression, resources.get('hour'), resources.get('hours')), expression) | |
9 | + end | |
10 | + | |
11 | + def between_description_format(expression) | |
12 | + resources.get('between_x_and_y') | |
13 | + end | |
14 | + | |
15 | + def description_format(expression) | |
16 | + resources.get('at_x') | |
17 | + end | |
18 | + | |
19 | + def starting_description_format(expression) | |
20 | + resources.get('starting') + ' ' + description_format(expression) | |
21 | + end | |
22 | + end | |
23 | +end | ... | ... |
1 | +++ a/lib/cronex/description/minutes.rb | |
... | ... | @@ -0,0 +1,27 @@ |
1 | +module Cronex | |
2 | + class MinutesDescription < Description | |
3 | + def single_item_description(expression) | |
4 | + Cronex::Utils.format_minutes(expression) | |
5 | + end | |
6 | + | |
7 | + def interval_description_format(expression) | |
8 | + format(resources.get('every_x') + ' ' + min_plural(expression), expression) | |
9 | + end | |
10 | + | |
11 | + def between_description_format(expression) | |
12 | + resources.get('minutes_through_past_the_hour') | |
13 | + end | |
14 | + | |
15 | + def description_format(expression) | |
16 | + expression == '0' ? '' : [resources.get('at_x'), min_plural(expression), resources.get('past_the_hour')].join(' ') | |
17 | + end | |
18 | + | |
19 | + def starting_description_format(expression) | |
20 | + resources.get('starting') + ' ' + description_format(expression) | |
21 | + end | |
22 | + | |
23 | + def min_plural(expression) | |
24 | + plural(expression, resources.get('minute'), resources.get('minutes')) | |
25 | + end | |
26 | + end | |
27 | +end | ... | ... |
1 | +++ a/lib/cronex/description/month.rb | |
... | ... | @@ -0,0 +1,23 @@ |
1 | +module Cronex | |
2 | + class MonthDescription < Description | |
3 | + def single_item_description(expression) | |
4 | + resources.get(DateTime.new(Time.now.year, Cronex::Utils.integer(expression), 1).strftime('%B').downcase) | |
5 | + end | |
6 | + | |
7 | + def interval_description_format(expression) | |
8 | + format(', ' + resources.get('every_x') + ' ' + plural(expression, resources.get('month'), resources.get('months')), expression) | |
9 | + end | |
10 | + | |
11 | + def between_description_format(expression) | |
12 | + ', ' + resources.get('between_description_format') | |
13 | + end | |
14 | + | |
15 | + def description_format(expression) | |
16 | + ', ' + resources.get('only_in') | |
17 | + end | |
18 | + | |
19 | + def starting_description_format(expression) | |
20 | + resources.get('starting') + ' ' + resources.get('in_x') | |
21 | + end | |
22 | + end | |
23 | +end | ... | ... |
1 | +++ a/lib/cronex/description/seconds.rb | |
... | ... | @@ -0,0 +1,23 @@ |
1 | +module Cronex | |
2 | + class SecondsDescription < Description | |
3 | + def single_item_description(expression) | |
4 | + expression | |
5 | + end | |
6 | + | |
7 | + def interval_description_format(expression) | |
8 | + format(resources.get('every_x_seconds'), expression) | |
9 | + end | |
10 | + | |
11 | + def between_description_format(expression) | |
12 | + resources.get('seconds_through_past_the_minute') | |
13 | + end | |
14 | + | |
15 | + def description_format(expression) | |
16 | + resources.get('at_x_seconds_past_the_minute') | |
17 | + end | |
18 | + | |
19 | + def starting_description_format(expression) | |
20 | + resources.get('starting') + ' ' + description_format(expression) | |
21 | + end | |
22 | + end | |
23 | +end | ... | ... |
1 | +++ a/lib/cronex/description/year.rb | |
... | ... | @@ -0,0 +1,23 @@ |
1 | +module Cronex | |
2 | + class YearDescription < Description | |
3 | + def single_item_description(expression) | |
4 | + DateTime.new(Cronex::Utils.integer(expression)).strftime('%Y') | |
5 | + end | |
6 | + | |
7 | + def interval_description_format(expression) | |
8 | + format(', ' + resources.get('every_x') + ' ' + plural(expression, resources.get('year'), resources.get('years')), expression) | |
9 | + end | |
10 | + | |
11 | + def between_description_format(expression) | |
12 | + ', ' + resources.get('between_description_format') | |
13 | + end | |
14 | + | |
15 | + def description_format(expression) | |
16 | + ', ' + resources.get('only_in') | |
17 | + end | |
18 | + | |
19 | + def starting_description_format(expression) | |
20 | + resources.get('starting') + ' ' + resources.get('in_x') | |
21 | + end | |
22 | + end | |
23 | +end | ... | ... |
1 | +++ a/lib/cronex/exp_descriptor.rb | |
... | ... | @@ -0,0 +1,194 @@ |
1 | +require 'unicode' | |
2 | + | |
3 | +module Cronex | |
4 | + | |
5 | + CASINGS = [:title, :sentence, :lower] | |
6 | + SEGMENTS = [:seconds, :minutes, :hours, :dayofmonth, :month, :dayofweek, :year, :timeofday, :full] | |
7 | + | |
8 | + SPECIAL_CHARS = ['/', '-', ',', '*'] | |
9 | + | |
10 | + CRONEX_OPTS = { | |
11 | + casing: :sentence, | |
12 | + verbose: false, | |
13 | + zero_based_dow: true, | |
14 | + use_24_hour_time_format: false, | |
15 | + throw_exception_on_parse_error: true, | |
16 | + strict_quartz: false, | |
17 | + locale: nil, | |
18 | + timezone: nil | |
19 | + } | |
20 | + | |
21 | + class ExpressionDescriptor | |
22 | + attr_accessor :expression, :expression_parts, :options, :parsed, :resources, :timezone | |
23 | + | |
24 | + def initialize(expression, options = {}) | |
25 | + @expression = expression | |
26 | + @options = CRONEX_OPTS.merge(options) | |
27 | + @expression_parts = [] | |
28 | + @parsed = false | |
29 | + @resources = Cronex::Resource.new(@options[:locale]) | |
30 | + @timezone = @options[:timezone] || 'UTC' | |
31 | + end | |
32 | + | |
33 | + def to_hash | |
34 | + Hash[SEGMENTS.take(7).zip(expression_parts)] | |
35 | + end | |
36 | + | |
37 | + def description(type = :full) | |
38 | + desc = '' | |
39 | + | |
40 | + begin | |
41 | + unless parsed | |
42 | + parser = Parser.new(expression, options) | |
43 | + @expression_parts = parser.parse | |
44 | + @parsed = true | |
45 | + end | |
46 | + | |
47 | + desc = case type | |
48 | + when :full | |
49 | + full_description(expression_parts) | |
50 | + when :timeofday | |
51 | + time_of_day_description(expression_parts) | |
52 | + when :hours | |
53 | + hours_description(expression_parts) | |
54 | + when :minutes | |
55 | + minutes_description(expression_parts) | |
56 | + when :seconds | |
57 | + seconds_description(expression_parts) | |
58 | + when :dayofmonth | |
59 | + day_of_month_description(expression_parts) | |
60 | + when :month | |
61 | + month_description(expression_parts) | |
62 | + when :dayofweek | |
63 | + day_of_week_description(expression_parts) | |
64 | + when :year | |
65 | + year_description(expression_parts) | |
66 | + else | |
67 | + seconds_description(expression_parts) | |
68 | + end | |
69 | + rescue StandardError => e | |
70 | + if options[:throw_exception_on_parse_error] | |
71 | + raise e | |
72 | + else | |
73 | + desc = e.message | |
74 | + puts "Exception parsing expression: #{e}" | |
75 | + end | |
76 | + end | |
77 | + | |
78 | + desc | |
79 | + end | |
80 | + | |
81 | + def seconds_description(expression_parts) | |
82 | + desc = SecondsDescription.new(resources) | |
83 | + desc.segment_description(expression_parts[0], resources.get('every_second')) | |
84 | + end | |
85 | + | |
86 | + def minutes_description(expression_parts) | |
87 | + desc = MinutesDescription.new(resources) | |
88 | + desc.segment_description(expression_parts[1], resources.get('every_minute')) | |
89 | + end | |
90 | + | |
91 | + def hours_description(expression_parts) | |
92 | + desc = HoursDescription.new(resources) | |
93 | + desc.segment_description(expression_parts[2], resources.get('every_hour')) | |
94 | + end | |
95 | + | |
96 | + def year_description(expression_parts) | |
97 | + desc = YearDescription.new(resources, options) | |
98 | + desc.segment_description(expression_parts[6], ', ' + resources.get('every_year')) | |
99 | + end | |
100 | + | |
101 | + def day_of_week_description(expression_parts) | |
102 | + desc = DayOfWeekDescription.new(resources, options) | |
103 | + desc.segment_description(expression_parts[5], ', ' + resources.get('every_day')) | |
104 | + end | |
105 | + | |
106 | + def month_description(expression_parts) | |
107 | + desc = MonthDescription.new(resources) | |
108 | + desc.segment_description(expression_parts[4], '') | |
109 | + end | |
110 | + | |
111 | + def day_of_month_description(expression_parts) | |
112 | + exp = expression_parts[3].gsub('?', '*') | |
113 | + if exp == 'L' | |
114 | + description = ', ' + resources.get('on_the_last_day_of_the_month') | |
115 | + elsif exp == 'LW' || exp == 'WL' | |
116 | + description = ', ' + resources.get('on_the_last_weekday_of_the_month') | |
117 | + else | |
118 | + match = exp.match(/(\d{1,2}W)|(W\d{1,2})/) | |
119 | + if match | |
120 | + day_num = Cronex::Utils.integer(match[0].gsub('W', '')) | |
121 | + day_str = day_num == 1 ? resources.get('first_weekday') : format(resources.get('weekday_nearest_day'), day_num) | |
122 | + description = format(', ' + resources.get('on_the_of_the_month'), day_str) | |
123 | + else | |
124 | + desc = DayOfMonthDescription.new(resources) | |
125 | + description = desc.segment_description(exp, ', ' + resources.get('every_day')) | |
126 | + end | |
127 | + end | |
128 | + description | |
129 | + end | |
130 | + | |
131 | + def time_of_day_description(expression_parts) | |
132 | + sec_exp, min_exp, hour_exp = expression_parts | |
133 | + description = '' | |
134 | + if [sec_exp, min_exp, hour_exp].all? { |exp| !Cronex::Utils.include_any?(exp, SPECIAL_CHARS) } | |
135 | + # specific time of day (i.e. 10 14) | |
136 | + description += resources.get('at') + ' ' + Cronex::Utils.format_time(hour_exp, min_exp, sec_exp, timezone) | |
137 | + elsif min_exp.include?('-') && !min_exp.include?('/') && !min_exp.include?(',') && !Cronex::Utils.include_any?(hour_exp, SPECIAL_CHARS) | |
138 | + # Minute range in single hour (e.g. 0-10 11) | |
139 | + min_parts = min_exp.split('-') | |
140 | + description += format( | |
141 | + resources.get('every_minute_between'), | |
142 | + Cronex::Utils.format_time(hour_exp, min_parts[0], '', timezone), | |
143 | + Cronex::Utils.format_time(hour_exp, min_parts[1], '', timezone)) | |
144 | + elsif hour_exp.include?(',') && !Cronex::Utils.include_any?(min_exp, SPECIAL_CHARS) | |
145 | + # Hours list with single minute (e.g. 30 6,14,16) | |
146 | + hour_parts = hour_exp.split(',') | |
147 | + description += resources.get('at') | |
148 | + h_parts = hour_parts.map { |part| ' ' + Cronex::Utils.format_time(part, min_exp, '', timezone) } | |
149 | + description += h_parts[0...-1].join(',') + ' ' + resources.get('and') + h_parts.last | |
150 | + else | |
151 | + sec_desc = seconds_description(expression_parts) | |
152 | + min_desc = minutes_description(expression_parts) | |
153 | + hour_desc = hours_description(expression_parts) | |
154 | + description += sec_desc | |
155 | + description += ', ' if description.size > 0 && !min_desc.empty? | |
156 | + description += min_desc | |
157 | + description += ', ' if description.size > 0 && !hour_desc.empty? | |
158 | + description += hour_desc | |
159 | + end | |
160 | + description | |
161 | + end | |
162 | + | |
163 | + def full_description(expression_parts) | |
164 | + time_segment = time_of_day_description(expression_parts) | |
165 | + dom_desc = day_of_month_description(expression_parts) | |
166 | + month_desc = month_description(expression_parts) | |
167 | + dow_desc = day_of_week_description(expression_parts) | |
168 | + year_desc = year_description(expression_parts) | |
169 | + description = format('%s%s%s%s%s', time_segment, dom_desc, dow_desc, month_desc, year_desc) | |
170 | + description = transform_verbosity(description, options[:verbose]) | |
171 | + description = transform_case(description, options[:casing]) | |
172 | + description | |
173 | + end | |
174 | + | |
175 | + def transform_case(desc, case_type = :lower) | |
176 | + case case_type | |
177 | + when :sentence | |
178 | + desc.sub(/\b[[:word:]]/u) { |s| Unicode.upcase(s) } | |
179 | + when :title | |
180 | + desc.gsub(/\b[[:word:]]/u) { |s| Unicode.upcase(s) } | |
181 | + else | |
182 | + Unicode.downcase(desc) | |
183 | + end | |
184 | + end | |
185 | + | |
186 | + def transform_verbosity(desc, verbose = false) | |
187 | + return desc if verbose | |
188 | + parts = %w(every_minute every_hour every_day) | |
189 | + parts.each { |part| desc.gsub!(resources.get(part.gsub('_', '_1_')), resources.get(part)) } | |
190 | + parts.each { |part| desc.gsub!(', ' + resources.get(part), '') } | |
191 | + desc | |
192 | + end | |
193 | + end | |
194 | +end | ... | ... |
1 | +++ a/lib/cronex/parser.rb | |
... | ... | @@ -0,0 +1,93 @@ |
1 | +module Cronex | |
2 | + | |
3 | + DAYS = Date::ABBR_DAYNAMES.map(&:upcase) | |
4 | + MONTHS = Date::ABBR_MONTHNAMES[1..-1].map(&:upcase) | |
5 | + | |
6 | + DAY_NUM = Hash[DAYS.zip(0..(DAYS.size - 1))] | |
7 | + MONTH_NUM = Hash[MONTHS.zip(1..MONTHS.size)] | |
8 | + | |
9 | + # abbr dayname => long dayname | |
10 | + DAY_DAY = Hash[DAYS.zip(Date::DAYNAMES.map(&:upcase))] | |
11 | + | |
12 | + class Parser | |
13 | + attr_accessor :expression, :options | |
14 | + | |
15 | + def initialize(expression, options = {}) | |
16 | + @expression = expression | |
17 | + @options = options | |
18 | + end | |
19 | + | |
20 | + def parse(exp = expression) | |
21 | + parsed_parts = Array.new(7, '') | |
22 | + | |
23 | + fail ExpressionError, 'Error: Expression null or empty' unless Cronex::Utils.present?(exp) | |
24 | + parts = sanitize(exp).split(' ') | |
25 | + len = parts.size | |
26 | + | |
27 | + if len < 5 | |
28 | + fail ExpressionError, "Error: Expression only has #{len} parts. At least 5 parts are required" | |
29 | + elsif len == 5 | |
30 | + fail ExpressionError, "Error: Expression only has 5 parts. For 'strict_quartz' option, at least 6 parts are required" if options[:strict_quartz] | |
31 | + # 5 part CRON so shift array past seconds element | |
32 | + parsed_parts.insert(1, *parts) | |
33 | + elsif len == 6 | |
34 | + # if last element ends with 4 digits, a year element has been supplied and no seconds element | |
35 | + if parts.last.match(/\d{4}$/) | |
36 | + parsed_parts.insert(1, *parts) | |
37 | + else | |
38 | + parsed_parts.insert(0, *parts) | |
39 | + end | |
40 | + elsif len == 7 | |
41 | + parsed_parts = parts | |
42 | + else | |
43 | + fail ExpressionError, "Error: Expression has too many parts (#{len}). Expression must not have more than 7 parts" | |
44 | + end | |
45 | + | |
46 | + parsed_parts = parsed_parts.take(7) # ; p parsed_parts | |
47 | + normalize(parsed_parts, options) | |
48 | + end | |
49 | + | |
50 | + def sanitize(exp = expression) | |
51 | + # remove extra spaces | |
52 | + exp = exp.strip.gsub(/\s+/, ' ').upcase | |
53 | + # convert non-standard day names (e.g. THURS, TUES) to 3-letter names | |
54 | + DAY_DAY.each do |day, longname| | |
55 | + matched = exp.scan(/\W*(#{day}\w*)/).flatten.uniq | |
56 | + matched.each { |m| exp.gsub!(m, day) if longname.include?(m) } | |
57 | + end | |
58 | + exp | |
59 | + end | |
60 | + | |
61 | + def normalize(expression_parts, options = {}) | |
62 | + parts = expression_parts.dup | |
63 | + | |
64 | + # convert ? to * only for DOM and DOW | |
65 | + parts[3].gsub!('?', '*') | |
66 | + parts[5].gsub!('?', '*') | |
67 | + | |
68 | + # Convert 0/, 1/ to */ | |
69 | + parts[0].gsub!('0/', '*/') if parts[0].start_with?('0/') # seconds | |
70 | + parts[1].gsub!('0/', '*/') if parts[1].start_with?('0/') # minutes | |
71 | + parts[2].gsub!('0/', '*/') if parts[2].start_with?('0/') # hours | |
72 | + parts[3].gsub!('1/', '*/') if parts[3].start_with?('1/') # day of month | |
73 | + parts[4].gsub!('1/', '*/') if parts[4].start_with?('1/') # month | |
74 | + parts[5].gsub!('1/', '*/') if parts[5].start_with?('1/') # day of week | |
75 | + | |
76 | + # convert */1 to * | |
77 | + parts = parts.map { |part| part == '*/1' ? '*' : part } | |
78 | + | |
79 | + # convert SUN-SAT format to 0-6 format | |
80 | + DAY_NUM.each { |day, i| i += 1 if !options[:zero_based_dow]; parts[5].gsub!(day, i.to_s) } | |
81 | + | |
82 | + # convert JAN-DEC format to 1-12 format | |
83 | + MONTH_NUM.each { |month, i| parts[4].gsub!(month, i.to_s) } | |
84 | + | |
85 | + # convert 0 second to (empty) | |
86 | + parts[0] = '' if parts[0] == '0' | |
87 | + | |
88 | + # convert 0 DOW to 7 so that 0 for Sunday in zeroBasedDayOfWeek is valid | |
89 | + parts[5] = '7' if (!options || options[:zero_based_dow]) && parts[5] == '0' # ; p parts | |
90 | + parts | |
91 | + end | |
92 | + end | |
93 | +end | ... | ... |
1 | +++ a/lib/cronex/resource.rb | |
... | ... | @@ -0,0 +1,33 @@ |
1 | +module Cronex | |
2 | + | |
3 | + RESOURCES_DIR = File.expand_path('../../../resources', __FILE__) | |
4 | + | |
5 | + class Resource | |
6 | + attr_reader :locale, :messages | |
7 | + | |
8 | + def initialize(loc = :en) | |
9 | + self.locale = loc || :en | |
10 | + end | |
11 | + | |
12 | + def locale=(loc) | |
13 | + result = load(loc) | |
14 | + if result.nil? || result.empty? | |
15 | + fail ResourceError, "Error: Invalid resource file for '#{loc}' locale" | |
16 | + else | |
17 | + @locale = loc | |
18 | + @messages = result | |
19 | + end | |
20 | + end | |
21 | + | |
22 | + def load(loc) | |
23 | + file = File.join(RESOURCES_DIR, "resources_#{loc}.yml") | |
24 | + fail ResourceError, "Resource file #{file} for '#{loc}' locale not found" unless File.exist?(file) | |
25 | + YAML.load_file(file) | |
26 | + end | |
27 | + | |
28 | + def [](key) | |
29 | + @messages[key] | |
30 | + end | |
31 | + alias_method :get, :[] | |
32 | + end | |
33 | +end | ... | ... |
1 | +++ a/lib/cronex/utils.rb | |
... | ... | @@ -0,0 +1,47 @@ |
1 | +require 'tzinfo' | |
2 | + | |
3 | +module Cronex | |
4 | + module Utils | |
5 | + extend self | |
6 | + | |
7 | + def present?(str) | |
8 | + !str.to_s.strip.empty? | |
9 | + end | |
10 | + | |
11 | + def include_any?(str, chars) | |
12 | + chars.any? { |char| str.include?(char) } | |
13 | + end | |
14 | + | |
15 | + def number?(str) | |
16 | + integer(str) rescue nil | |
17 | + end | |
18 | + | |
19 | + def integer(str) | |
20 | + # strip leading zeros in numbers to prevent '08', '09' | |
21 | + # from being treated as invalid octals | |
22 | + Integer(str.sub(/^0*(\d+)/, '\1')) | |
23 | + end | |
24 | + | |
25 | + def day_of_week_name(number) | |
26 | + Date::DAYNAMES[number.to_i % 7] | |
27 | + end | |
28 | + | |
29 | + def format_minutes(minute_expression) | |
30 | + if minute_expression.include?(',') | |
31 | + minute_expression.split(',').map { |m| format('%02d', integer(m)) }.join(',') | |
32 | + else | |
33 | + format('%02d', integer(minute_expression)) | |
34 | + end | |
35 | + end | |
36 | + | |
37 | + def format_time(hour_expression, minute_expression, second_expression = '', timezone = 'UTC') | |
38 | + hour = integer(hour_expression) | |
39 | + minute = integer(minute_expression) | |
40 | + second = second_expression.to_s.empty? ? 0 : integer(second_expression) | |
41 | + tz = TZInfo::Timezone.get(timezone) | |
42 | + time = tz.utc_to_local(Date.today.to_time + hour * 60 * 60 + minute * 60 + second) | |
43 | + format = present?(second_expression) ? '%l:%M:%S %p' : '%l:%M %p' | |
44 | + time.strftime(format).lstrip | |
45 | + end | |
46 | + end | |
47 | +end | ... | ... |
1 | +++ a/resources/resources_de.yml | |
... | ... | @@ -0,0 +1,76 @@ |
1 | +# resources_de.yml | |
2 | +--- | |
3 | +expression_empty_exception: 'Ausdruck darf nicht null oder leer sein' | |
4 | +interval_description_format: 'jeden %s Tag der Woche' | |
5 | +between_description_format: '%s bis %s' | |
6 | +between_weekday_description_format: '%s bis %s' | |
7 | +on_the_day_of_the_month: 'am {{nth}} %s des Monats' | |
8 | +on_the_of_the_month: 'am %s des Monats' | |
9 | +on_the_last_of_the_month: 'am letzten %s des Monats' | |
10 | +on_the_last_day_of_the_month: 'am letzten Tag des Monats' | |
11 | +on_the_last_weekday_of_the_month: 'am letzen Werktag des Monats' | |
12 | +between_days_of_the_month: 'zwischen Tag %s und %s des Monats' | |
13 | +seconds_through_past_the_minute: 'Sekunden %s bis %s vergangene Minute' | |
14 | +between_x_and_y: 'zwischen %s und %s' | |
15 | +past_the_hour: 'vergangene Stunde' | |
16 | +at_x_seconds_past_the_minute: 'am %s Sekunden nach der vergangenen Minute' | |
17 | +minutes_through_past_the_hour: 'Minuten %s bis %s nach der vergangenen Stunde' | |
18 | +on_day_of_the_month: 'am %s Tag des Monats' | |
19 | +last_day: 'der letzte Tag' | |
20 | +first_weekday: 'Erster Wochentag' | |
21 | +weekday_nearest_day: 'Wochentag zum nächsten Tag %s' | |
22 | +starting: 'beginnend' | |
23 | +only_on: 'nur an %s' | |
24 | +only_in: 'nur in %s' | |
25 | +every_x_seconds: 'Alle %s Sekunden' | |
26 | +every_minute_between: 'Jede Minute zwischen %s und %s' | |
27 | +every_second: 'Jede Sekunde' | |
28 | +every_minute: 'Jede Minute' | |
29 | +every_1_minute: 'Jede 1. Minute' | |
30 | +every_hour: 'Jede Stunde' | |
31 | +every_1_hour: 'Jede 1. Stunde' | |
32 | +every_day: 'Jeden Tag' | |
33 | +every_1_day: 'Jeden 1. Tag' | |
34 | +every_year: 'Jedes Jahr' | |
35 | +every_x: 'Alle %s' | |
36 | +at_x: 'um %s' | |
37 | +on_x: 'an %s' | |
38 | +in_x: 'in %s' | |
39 | +first: ersten | |
40 | +second: zweiten | |
41 | +third: dritten | |
42 | +fourth: vierten | |
43 | +fifth: fünften | |
44 | +time_pm: PM | |
45 | +time_am: AM | |
46 | +and: und | |
47 | +at: Um | |
48 | +day: Tag | |
49 | +days: Tagen | |
50 | +hour: Stunde | |
51 | +hours: Stunden | |
52 | +minute: Minute | |
53 | +minutes: Minuten | |
54 | +month: Monat | |
55 | +months: Monaten | |
56 | +year: Jahr | |
57 | +years: Jahren | |
58 | +monday: Montag | |
59 | +tuesday: Dienstag | |
60 | +wednesday: Mittwoch | |
61 | +thursday: Donnerstag | |
62 | +friday: Freitag | |
63 | +saturday: Samstag | |
64 | +sunday: Sonntag | |
65 | +january: Januar | |
66 | +february: Februar | |
67 | +march: März | |
68 | +april: April | |
69 | +may: Mai | |
70 | +june: Juni | |
71 | +july: Juli | |
72 | +august: August | |
73 | +september: September | |
74 | +october: Oktober | |
75 | +november: November | |
76 | +december: Dezember | ... | ... |
1 | +++ a/resources/resources_en.yml | |
... | ... | @@ -0,0 +1,76 @@ |
1 | +# resources_en.yml | |
2 | +--- | |
3 | +expression_empty_exception: 'Expression cannot be null or empty' | |
4 | +interval_description_format: 'every %s days of the week' | |
5 | +between_description_format: '%s through %s' | |
6 | +between_weekday_description_format: '%s through %s' | |
7 | +on_the_day_of_the_month: 'on the {{nth}} %s of the month' | |
8 | +on_the_of_the_month: 'on the %s of the month' | |
9 | +on_the_last_of_the_month: 'on the last %s of the month' | |
10 | +on_the_last_day_of_the_month: 'on the last day of the month' | |
11 | +on_the_last_weekday_of_the_month: 'on the last weekday of the month' | |
12 | +between_days_of_the_month: 'between day %s and %s of the month' | |
13 | +seconds_through_past_the_minute: 'seconds %s through %s past the minute' | |
14 | +between_x_and_y: 'between %s and %s' | |
15 | +past_the_hour: 'past the hour' | |
16 | +at_x_seconds_past_the_minute: 'at %s seconds past the minute' | |
17 | +minutes_through_past_the_hour: 'minutes %s through %s past the hour' | |
18 | +on_day_of_the_month: 'on day %s of the month' | |
19 | +last_day: 'the last day' | |
20 | +first_weekday: 'first weekday' | |
21 | +weekday_nearest_day: 'weekday nearest day %s' | |
22 | +starting: 'starting' | |
23 | +only_on: 'only on %s' | |
24 | +only_in: 'only in %s' | |
25 | +every_x_seconds: 'every %s seconds' | |
26 | +every_minute_between: 'Every minute between %s and %s' | |
27 | +every_second: 'every second' | |
28 | +every_minute: 'every minute' | |
29 | +every_1_minute: 'every 1 minute' | |
30 | +every_hour: 'every hour' | |
31 | +every_1_hour: 'every 1 hour' | |
32 | +every_day: 'every day' | |
33 | +every_1_day: 'every 1 day' | |
34 | +every_year: 'every year' | |
35 | +every_x: 'every %s' | |
36 | +at_x: 'at %s' | |
37 | +on_x: 'on %s' | |
38 | +in_x: 'in %s' | |
39 | +first: first | |
40 | +second: second | |
41 | +third: third | |
42 | +fourth: fourth | |
43 | +fifth: fifth | |
44 | +time_pm: PM | |
45 | +time_am: AM | |
46 | +and: and | |
47 | +at: At | |
48 | +day: day | |
49 | +days: days | |
50 | +hour: hour | |
51 | +hours: hours | |
52 | +minute: minute | |
53 | +minutes: minutes | |
54 | +month: month | |
55 | +months: months | |
56 | +year: year | |
57 | +years: years | |
58 | +monday: Monday | |
59 | +tuesday: Tuesday | |
60 | +wednesday: Wednesday | |
61 | +thursday: Thursday | |
62 | +friday: Friday | |
63 | +saturday: Saturday | |
64 | +sunday: Sunday | |
65 | +january: January | |
66 | +february: February | |
67 | +march: March | |
68 | +april: April | |
69 | +may: May | |
70 | +june: June | |
71 | +july: July | |
72 | +august: August | |
73 | +september: September | |
74 | +october: October | |
75 | +november: November | |
76 | +december: December | ... | ... |
1 | +++ a/resources/resources_fr.yml | |
... | ... | @@ -0,0 +1,76 @@ |
1 | +# resources_fr.yml | |
2 | +--- | |
3 | +expression_empty_exception: "L'expression ne peut pas être nulle ou vide" | |
4 | +interval_description_format: 'tous les %s jours de la semaine' | |
5 | +between_description_format: '%s à %s' | |
6 | +between_weekday_description_format: '%s à %s' | |
7 | +on_the_day_of_the_month: 'le {{nth}} %s du mois' | |
8 | +on_the_of_the_month: 'le %s du mois' | |
9 | +on_the_last_of_the_month: 'le dernier %s du mois' | |
10 | +on_the_last_day_of_the_month: 'le dernier jour du mois' | |
11 | +on_the_last_weekday_of_the_month: 'le dernier jour en semaine du mois' | |
12 | +between_days_of_the_month: 'entre le jour %s et le %s du mois' | |
13 | +seconds_through_past_the_minute: 'secondes %s à %s après la minute' | |
14 | +between_x_and_y: 'entre %s et %s' | |
15 | +past_the_hour: "après l'heure" | |
16 | +at_x_seconds_past_the_minute: 'à %s secondes après la minute' | |
17 | +minutes_through_past_the_hour: "minutes %s à %s après l'heure" | |
18 | +on_day_of_the_month: 'le %s de chaque mois' | |
19 | +last_day: 'dernier jour' | |
20 | +first_weekday: 'premier jour de la semaine' | |
21 | +weekday_nearest_day: 'jour de semaine le plus proche du %s' | |
22 | +starting: 'commence' # départ | |
23 | +only_on: 'seulement le %s' # uniquement le | |
24 | +only_in: 'seulement en %s' | |
25 | +every_x_seconds: 'toutes les %s secondes' | |
26 | +every_minute_between: 'chaque minute entre %s et %s' | |
27 | +every_second: 'chaque seconde' | |
28 | +every_minute: 'chaque minute' | |
29 | +every_1_minute: 'toutes les 1 minutes' | |
30 | +every_hour: 'chaque heure' | |
31 | +every_1_hour: 'toutes les 1 heures' | |
32 | +every_day: 'chaque jour' | |
33 | +every_1_day: 'tous les 1 jours' | |
34 | +every_year: 'chaque année' | |
35 | +every_x: 'tous les %s' | |
36 | +at_x: 'à %s' | |
37 | +on_x: 'le %s' | |
38 | +in_x: 'en %s' | |
39 | +first: premier | |
40 | +second: second | |
41 | +third: troisième | |
42 | +fourth: quatrième | |
43 | +fifth: cinquième | |
44 | +time_pm: PM | |
45 | +time_am: AM | |
46 | +and: et | |
47 | +at: À | |
48 | +day: jour | |
49 | +days: jours | |
50 | +hour: heure | |
51 | +hours: heures | |
52 | +minute: minute | |
53 | +minutes: minutes | |
54 | +month: mois | |
55 | +months: mois | |
56 | +year: an | |
57 | +years: ans | |
58 | +monday: lundi | |
59 | +tuesday: mardi | |
60 | +wednesday: mercredi | |
61 | +thursday: jeudi | |
62 | +friday: vendredi | |
63 | +saturday: samedi | |
64 | +sunday: dimanche | |
65 | +january: janvier | |
66 | +february: février | |
67 | +march: mars | |
68 | +april: avril | |
69 | +may: mai | |
70 | +june: juin | |
71 | +july: juillet | |
72 | +august: août | |
73 | +september: septembre | |
74 | +october: octobre | |
75 | +november: novembre | |
76 | +december: décembre | ... | ... |
1 | +++ a/resources/resources_it.yml | |
... | ... | @@ -0,0 +1,76 @@ |
1 | +# resources_it.yml | |
2 | +--- | |
3 | +expression_empty_exception: "L'espressione non puó essere null o vuota" | |
4 | +interval_description_format: '%s giorni alla settimana' | |
5 | +between_description_format: 'da %s a %s' | |
6 | +between_weekday_description_format: 'da %s a %s' | |
7 | +on_the_day_of_the_month: 'il(la) {{nth}}(a) %s del mese' | |
8 | +on_the_of_the_month: 'il %s del mese' | |
9 | +on_the_last_of_the_month: "l'ultimo(a) %s del mese" | |
10 | +on_the_last_day_of_the_month: "l'ultimo giorno del mese" | |
11 | +on_the_last_weekday_of_the_month: "l'ultimo giorno lavorativo del mese" | |
12 | +between_days_of_the_month: 'tra il giorno %s e il %s del mese' | |
13 | +seconds_through_past_the_minute: 'dal secondo %s al %s dopo il minuto' | |
14 | +between_x_and_y: 'tra le %s e le %s' | |
15 | +past_the_hour: "dopo l'ora" | |
16 | +at_x_seconds_past_the_minute: 'a %s secondi dopo il minuto' | |
17 | +minutes_through_past_the_hour: "dal minuto %s al %s dopo l'ora" | |
18 | +on_day_of_the_month: 'il giorno %s del mese' | |
19 | +last_day: 'ultimo giorno' | |
20 | +first_weekday: 'il primo giorno della settimana lavorativa' | |
21 | +weekday_nearest_day: 'il prossimo giorno %s della settimana lavorativa' | |
22 | +starting: 'a partire da' | |
23 | +only_on: 'solo di %s' | |
24 | +only_in: 'solo a(nel) %s' | |
25 | +every_x_seconds: 'ogni %s secondi' | |
26 | +every_minute_between: 'ogni minuto tra le %s e le %s' | |
27 | +every_second: 'ogni secondo' | |
28 | +every_minute: 'ogni minuto' | |
29 | +every_1_minute: 'ogni minuto' | |
30 | +every_hour: 'ogni ora' | |
31 | +every_1_hour: 'ogni ora' | |
32 | +every_day: 'ogni giorno' | |
33 | +every_1_day: 'ogni giorno' | |
34 | +every_year: 'ogni anno' | |
35 | +every_x: 'ogni %s' | |
36 | +at_x: 'alle(ai) %s' | |
37 | +on_x: 'il %s' | |
38 | +in_x: '%s' | |
39 | +first: primo | |
40 | +second: secondo | |
41 | +third: terzo | |
42 | +fourth: quarto | |
43 | +fifth: quinto | |
44 | +time_pm: pomeriggio | |
45 | +time_am: mattino | |
46 | +and: e | |
47 | +at: alle(ai) | |
48 | +day: giorno | |
49 | +days: giorni | |
50 | +hour: ora | |
51 | +hours: ore | |
52 | +minute: minuto | |
53 | +minutes: minuti | |
54 | +month: mese | |
55 | +months: mesi | |
56 | +year: anno | |
57 | +years: anni | |
58 | +monday: lunedì | |
59 | +tuesday: martedì | |
60 | +wednesday: mercoledì | |
61 | +thursday: giovedì | |
62 | +friday: venerdì | |
63 | +saturday: sabato | |
64 | +sunday: domenica | |
65 | +january: gennaio | |
66 | +february: febbraio | |
67 | +march: marzo | |
68 | +april: aprile | |
69 | +may: maggio | |
70 | +june: giugno | |
71 | +july: luglio | |
72 | +august: agosto | |
73 | +september: settembre | |
74 | +october: ottobre | |
75 | +november: novembre | |
76 | +december: dicembre | ... | ... |
1 | +++ a/resources/resources_pt_BR.yml | |
... | ... | @@ -0,0 +1,76 @@ |
1 | +# resources_pt_BR.yml | |
2 | +--- | |
3 | +expression_empty_exception: 'A expressão não pode ser nula ou vazia' | |
4 | +interval_description_format: 'a cada %s dias da semana' | |
5 | +between_description_format: 'de %s a %s' | |
6 | +between_weekday_description_format: 'de %s a %s' | |
7 | +on_the_day_of_the_month: 'no(a) {{nth}} %s do mês' | |
8 | +on_the_of_the_month: 'no %s do mês' | |
9 | +on_the_last_of_the_month: 'no(a) último(a) %s do mês' | |
10 | +on_the_last_day_of_the_month: 'no último dia do mês' | |
11 | +on_the_last_weekday_of_the_month: 'no último dia útil do mês' | |
12 | +between_days_of_the_month: 'entre os dias %s e %s do mês' | |
13 | +seconds_through_past_the_minute: 'entre %s e %s segundos após o minuto' | |
14 | +between_x_and_y: 'entre %s e %s' | |
15 | +past_the_hour: 'após a hora' | |
16 | +at_x_seconds_past_the_minute: '%s segundos após o minuto' | |
17 | +minutes_through_past_the_hour: 'entre %s e %s minutos após a hora' | |
18 | +on_day_of_the_month: 'no dia %s do mês' | |
19 | +last_day: 'último dia' | |
20 | +first_weekday: 'primeiro dia útil' | |
21 | +weekday_nearest_day: 'dia útil mais próximo a %s' | |
22 | +starting: 'iniciando' | |
23 | +only_on: 'todo(a) %s' | |
24 | +only_in: 'em %s' | |
25 | +every_x_seconds: 'a cada %s segundos' | |
26 | +every_minute_between: 'A cada minuto entre %s e %s' | |
27 | +every_second: 'a cada segundo' | |
28 | +every_minute: 'a cada minuto' | |
29 | +every_1_minute: 'a cada 1 minuto' | |
30 | +every_hour: 'a cada hora' | |
31 | +every_1_hour: 'a cada 1 hora' | |
32 | +every_day: 'todo dia' | |
33 | +every_1_day: 'a cada 1 dia' | |
34 | +every_year: 'a cada ano' | |
35 | +every_x: 'a cada %s' | |
36 | +at_x: '%s' | |
37 | +on_x: '%s' | |
38 | +in_x: 'em %s' | |
39 | +first: primeiro(a) | |
40 | +second: segundo(a) | |
41 | +third: terceiro(a) | |
42 | +fourth: quarto(a) | |
43 | +fifth: quinto(a) | |
44 | +time_pm: após meio-dia | |
45 | +time_am: antes do meio-dia | |
46 | +and: e | |
47 | +at: às | |
48 | +day: dia | |
49 | +days: dias | |
50 | +hour: hora | |
51 | +hours: horas | |
52 | +minute: minuto | |
53 | +minutes: minutos | |
54 | +month: mês | |
55 | +months: mêses | |
56 | +year: ano | |
57 | +years: anos | |
58 | +monday: segunda-feira | |
59 | +tuesday: terça-feira | |
60 | +wednesday: quarta-feira | |
61 | +thursday: quinta-feira | |
62 | +friday: sexta-feira | |
63 | +saturday: sábado | |
64 | +sunday: domingo | |
65 | +january: janeiro | |
66 | +february: fevereiro | |
67 | +march: março | |
68 | +april: abril | |
69 | +may: maio | |
70 | +june: junho | |
71 | +july: julho | |
72 | +august: agosto | |
73 | +september: setembro | |
74 | +october: outubro | |
75 | +november: novembro | |
76 | +december: dezembro | ... | ... |
1 | +++ a/resources/resources_ro.yml | |
... | ... | @@ -0,0 +1,76 @@ |
1 | +# resources_ro.yml | |
2 | +--- | |
3 | +expression_empty_exception: 'Expresia nu poate fi vidă sau nulă' | |
4 | +interval_description_format: 'în fiecare %s zile din săptămână' | |
5 | +between_description_format: 'din %s până în %s' | |
6 | +between_weekday_description_format: 'de %s până %s' | |
7 | +on_the_day_of_the_month: 'în {{nth}} %s a lunii' | |
8 | +on_the_of_the_month: 'în %s ale lunii' | |
9 | +on_the_last_of_the_month: 'în ultima %s din lună' | |
10 | +on_the_last_day_of_the_month: 'în ultima zi a lunii' | |
11 | +on_the_last_weekday_of_the_month: 'în ultima zi din săptămână a lunii' | |
12 | +between_days_of_the_month: 'între zilele %s și %s a lunii' | |
13 | +seconds_through_past_the_minute: 'între secundele %s și %s' | |
14 | +between_x_and_y: 'între %s și %s' | |
15 | +past_the_hour: 'în fiecare oră' | |
16 | +at_x_seconds_past_the_minute: 'la secunda %s' | |
17 | +minutes_through_past_the_hour: 'între minutele %s și %s' | |
18 | +on_day_of_the_month: 'în a %s-a zi a lunii' | |
19 | +last_day: 'ultima zi' | |
20 | +first_weekday: 'prima zi din săptămână' | |
21 | +weekday_nearest_day: 'cea mai apropiată %s din săptămână' | |
22 | +starting: pornire | |
23 | +only_on: 'numai %s' | |
24 | +only_in: 'numai în %s' | |
25 | +every_x_seconds: 'la fiecare %s secunde' | |
26 | +every_minute_between: 'în fiecare minut între %s și %s' | |
27 | +every_second: 'în fiecare secundă' | |
28 | +every_minute: 'în fiecare minut' | |
29 | +every_1_minute: 'din minut în minut' | |
30 | +every_hour: 'în fiecare oră' | |
31 | +every_1_hour: 'din oră în oră' | |
32 | +every_day: 'în fiecare zi' | |
33 | +every_1_day: 'în fiecare zi' | |
34 | +every_year: 'în fiecare an' | |
35 | +every_x: 'la fiecare %s' | |
36 | +at_x: 'la %s' | |
37 | +on_x: 'de %s' | |
38 | +in_x: 'în %s' | |
39 | +first: prima | |
40 | +second: 'a doua' | |
41 | +third: 'a treia' | |
42 | +fourth: 'a patra' | |
43 | +fifth: 'a cincea' | |
44 | +time_pm: PM | |
45 | +time_am: AM | |
46 | +and: și | |
47 | +at: la | |
48 | +day: zi | |
49 | +days: zile | |
50 | +hour: oră | |
51 | +hours: ore | |
52 | +minute: minut | |
53 | +minutes: minute | |
54 | +month: lună | |
55 | +months: luni | |
56 | +year: an | |
57 | +years: ani | |
58 | +monday: luni | |
59 | +tuesday: marți | |
60 | +wednesday: miercuri | |
61 | +thursday: joi | |
62 | +friday: vineri | |
63 | +saturday: sâmbătă | |
64 | +sunday: duminică | |
65 | +january: ianuarie | |
66 | +february: februarie | |
67 | +march: martie | |
68 | +april: aprilie | |
69 | +may: mai | |
70 | +june: iunie | |
71 | +july: iulie | |
72 | +august: august | |
73 | +september: septembrie | |
74 | +october: octombrie | |
75 | +november: noiembrie | |
76 | +december: decembrie | ... | ... |
1 | +++ a/resources/resources_ru.yml | |
... | ... | @@ -0,0 +1,76 @@ |
1 | +# resources_ru.yml | |
2 | +--- | |
3 | +expression_empty_exception: 'Выражение не может быть нулевым или пустым' | |
4 | +interval_description_format: 'каждые %s дня(ей) недели' | |
5 | +between_description_format: '%s - %s' | |
6 | +between_weekday_description_format: '%s - %s' | |
7 | +on_the_day_of_the_month: 'в {{nth}} %s месяца' | |
8 | +on_the_of_the_month: 'в %s месяца' | |
9 | +on_the_last_of_the_month: 'в последний %s месяца' | |
10 | +on_the_last_day_of_the_month: 'в последний день месяца' | |
11 | +on_the_last_weekday_of_the_month: 'в последний будний день месяца' | |
12 | +between_days_of_the_month: 'между %s днем и %s днем месяца' | |
13 | +seconds_through_past_the_minute: 'секунды с %s по %s' | |
14 | +between_x_and_y: 'между %s и %s' | |
15 | +past_the_hour: 'часа' | |
16 | +at_x_seconds_past_the_minute: 'в %s секунд' | |
17 | +minutes_through_past_the_hour: 'минуты с %s по %s' | |
18 | +on_day_of_the_month: '%s день месяца' | |
19 | +last_day: 'последним' | |
20 | +first_weekday: 'первый будний день' | |
21 | +weekday_nearest_day: 'ближайший будний день к %s' | |
22 | +starting: начало | |
23 | +only_on: 'только %s' | |
24 | +only_in: 'только %s' | |
25 | +every_x_seconds: 'каждые %s секунд' | |
26 | +every_minute_between: 'каждую минуту с %s по %s' | |
27 | +every_second: 'каждую секунду' | |
28 | +every_minute: 'каждую минуту' | |
29 | +every_1_minute: 'каждую минуту' | |
30 | +every_hour: 'каждый час' | |
31 | +every_1_hour: 'каждый час' | |
32 | +every_day: 'каждый день' | |
33 | +every_1_day: 'каждый день' | |
34 | +every_year: 'каждый год' | |
35 | +every_x: 'каждые %s' | |
36 | +at_x: 'в %s' | |
37 | +on_x: 'в %s' | |
38 | +in_x: 'в %s' | |
39 | +first: первый | |
40 | +second: второй | |
41 | +third: третий | |
42 | +fourth: четвертый | |
43 | +fifth: пятый | |
44 | +time_pm: PM | |
45 | +time_am: AM | |
46 | +and: и | |
47 | +at: В | |
48 | +day: день | |
49 | +days: дня(ей) | |
50 | +hour: час | |
51 | +hours: часов | |
52 | +minute: минута | |
53 | +minutes: минут | |
54 | +month: месяц | |
55 | +months: месяцев | |
56 | +year: год | |
57 | +years: лет | |
58 | +monday: понедельник | |
59 | +tuesday: вторник | |
60 | +wednesday: среда | |
61 | +thursday: четверг | |
62 | +friday: пятница | |
63 | +saturday: суббота | |
64 | +sunday: воскресенье | |
65 | +january: январь | |
66 | +february: февраль | |
67 | +march: март | |
68 | +april: апрель | |
69 | +may: май | |
70 | +june: июнь | |
71 | +july: июль | |
72 | +august: август | |
73 | +september: сентябрь | |
74 | +october: октябрь | |
75 | +november: ноябрь | |
76 | +december: декабрь | ... | ... |
1 | +++ a/resources/resources_zh-CN.yml | |
... | ... | @@ -0,0 +1,76 @@ |
1 | +# resources_zh_CN.yml | |
2 | +--- | |
3 | +expression_empty_exception: '表达式不能为空' | |
4 | +interval_description_format: '每隔%s天' | |
5 | +between_description_format: '%s至%s' | |
6 | +between_weekday_description_format: '%s至%s' | |
7 | +on_the_day_of_the_month: '在月份的第{{nth}}个%s' | |
8 | +on_the_of_the_month: '在月份的%s' | |
9 | +on_the_last_of_the_month: '在月份的最后一个%s' | |
10 | +on_the_last_day_of_the_month: '在月份的最后一天' | |
11 | +on_the_last_weekday_of_the_month: '在月份的最后一个工作日' | |
12 | +between_days_of_the_month: '在月份的%s至%s号之间' | |
13 | +seconds_through_past_the_minute: '在分钟之后的%s至%s秒' | |
14 | +between_x_and_y: '在%s至%s之间' | |
15 | +past_the_hour: '小时过后' | |
16 | +at_x_seconds_past_the_minute: '在分钟过后的%s秒' | |
17 | +minutes_through_past_the_hour: '在小时之后的%s至%s分钟' | |
18 | +on_day_of_the_month: '在月份的第%s号' | |
19 | +last_day: '最后一天' | |
20 | +first_weekday: '第一个工作日' | |
21 | +weekday_nearest_day: '最接近工作日%s' | |
22 | +starting: '开始' | |
23 | +only_on: '仅在%s' | |
24 | +only_in: '仅在%s' | |
25 | +every_x_seconds: '每隔%s秒' | |
26 | +every_minute_between: '每分钟%d至%d之间' | |
27 | +every_second: '每秒' | |
28 | +every_minute: '每分钟' | |
29 | +every_1_minute: '每1分钟' | |
30 | +every_hour: '每小时' | |
31 | +every_1_hour: '每1小时' | |
32 | +every_day: '每天' | |
33 | +every_1_day: '每1天' | |
34 | +every_year: '每年' | |
35 | +every_x: '每隔%s' | |
36 | +at_x: '在%s' | |
37 | +on_x: '在%s' | |
38 | +in_x: '在%s' | |
39 | +first: '第一' | |
40 | +second: '第二' | |
41 | +third: '第三' | |
42 | +fourth: '第四' | |
43 | +fifth: '第五' | |
44 | +time_pm: '下午' | |
45 | +time_am: '上午' | |
46 | +and: '和' | |
47 | +at: '在' | |
48 | +day: '天' | |
49 | +days: '天' | |
50 | +hour: '小时' | |
51 | +hours: '小时' | |
52 | +minute: '分钟' | |
53 | +minutes: '分钟' | |
54 | +month: '月' | |
55 | +months: '月' | |
56 | +year: '年' | |
57 | +years: '年' | |
58 | +monday: '星期一' | |
59 | +tuesday: '星期二' | |
60 | +wednesday: '星期三' | |
61 | +thursday: '星期四' | |
62 | +friday: '星期五' | |
63 | +saturday: '星期六' | |
64 | +sunday: '星期日' | |
65 | +january: '一月' | |
66 | +february: '二月' | |
67 | +march: '三月' | |
68 | +april: '四月' | |
69 | +may: '五月' | |
70 | +june: '六月' | |
71 | +july: '七月' | |
72 | +august: '八月' | |
73 | +september: '九月' | |
74 | +october: '十月' | |
75 | +november: '十一月' | |
76 | +december: '十二月' | |
0 | 77 | \ No newline at end of file | ... | ... |
1 | +++ a/resources/resources_zh-TW.yml | |
... | ... | @@ -0,0 +1,76 @@ |
1 | +# resources_zh_TW.yml | |
2 | +--- | |
3 | +expression_empty_exception: '表達式不能為空' | |
4 | +interval_description_format: '每隔%s天' | |
5 | +between_description_format: '%s至%s' | |
6 | +between_weekday_description_format: '%s至%s' | |
7 | +on_the_day_of_the_month: '在月份的第{{nth}}個%s' | |
8 | +on_the_of_the_month: '在月份的%s' | |
9 | +on_the_last_of_the_month: '在月份的最後一個%s' | |
10 | +on_the_last_day_of_the_month: '在月份的最後一天' | |
11 | +on_the_last_weekday_of_the_month: '在月份的最後一個工作日' | |
12 | +between_days_of_the_month: '在月份的%s至%s號之間' | |
13 | +seconds_through_past_the_minute: '在分鐘之後的%s至%s秒' | |
14 | +between_x_and_y: '在%s至%s之間' | |
15 | +past_the_hour: '小時過後' | |
16 | +at_x_seconds_past_the_minute: '在分鐘過後的%s秒' | |
17 | +minutes_through_past_the_hour: '在小時之後的%s至%s分鐘' | |
18 | +on_day_of_the_month: '在月份的第%s號' | |
19 | +last_day: '最後一天' | |
20 | +first_weekday: '第一個工作日' | |
21 | +weekday_nearest_day: '最接近工作日%s' | |
22 | +starting: '開始' | |
23 | +only_on: '僅在%s' | |
24 | +only_in: '僅在%s' | |
25 | +every_x_seconds: '每隔%s秒' | |
26 | +every_minute_between: '每分鐘%d至%d之間' | |
27 | +every_second: '每秒' | |
28 | +every_minute: '每分鐘' | |
29 | +every_1_minute: '每1分鐘' | |
30 | +every_hour: '每小時' | |
31 | +every_1_hour: '每1小時' | |
32 | +every_day: '每天' | |
33 | +every_1_day: '每1天' | |
34 | +every_year: '每年' | |
35 | +every_x: '每隔%s' | |
36 | +at_x: '在%s' | |
37 | +on_x: '在%s' | |
38 | +in_x: '在%s' | |
39 | +first: '第一' | |
40 | +second: '第二' | |
41 | +third: '第三' | |
42 | +fourth: '第四' | |
43 | +fifth: '第五' | |
44 | +time_pm: '下午' | |
45 | +time_am: '上午' | |
46 | +and: '和' | |
47 | +at: '在' | |
48 | +day: '天' | |
49 | +days: '天' | |
50 | +hour: '小時' | |
51 | +hours: '小時' | |
52 | +minute: '分鐘' | |
53 | +minutes: '分鐘' | |
54 | +month: '月' | |
55 | +months: '月' | |
56 | +year: '年' | |
57 | +years: '年' | |
58 | +monday: '星期一' | |
59 | +tuesday: '星期二' | |
60 | +wednesday: '星期三' | |
61 | +thursday: '星期四' | |
62 | +friday: '星期五' | |
63 | +saturday: '星期六' | |
64 | +sunday: '星期日' | |
65 | +january: '一月' | |
66 | +february: '二月' | |
67 | +march: '三月' | |
68 | +april: '四月' | |
69 | +may: '五月' | |
70 | +june: '六月' | |
71 | +july: '七月' | |
72 | +august: '八月' | |
73 | +september: '九月' | |
74 | +october: '十月' | |
75 | +november: '十一月' | |
76 | +december: '十二月' | |
0 | 77 | \ No newline at end of file | ... | ... |
1 | +++ a/spec/casing_spec.rb | |
... | ... | @@ -0,0 +1,22 @@ |
1 | +require 'cronex' | |
2 | + | |
3 | +module Cronex | |
4 | + describe ExpressionDescriptor do | |
5 | + | |
6 | + subject(:expression) { '* * * * *' } | |
7 | + | |
8 | + context 'casing:' do | |
9 | + it 'sentence' do | |
10 | + expect(desc(expression, casing: :sentence)).to eq('Every minute') | |
11 | + end | |
12 | + | |
13 | + it 'title' do | |
14 | + expect(desc(expression, casing: :title)).to eq('Every Minute') | |
15 | + end | |
16 | + | |
17 | + it 'lower' do | |
18 | + expect(desc(expression, casing: :lower)).to eq('every minute') | |
19 | + end | |
20 | + end | |
21 | + end | |
22 | +end | ... | ... |
1 | +++ a/spec/exp_descriptor_de_spec.rb | |
... | ... | @@ -0,0 +1,405 @@ |
1 | +# encoding: utf-8 | |
2 | +require 'cronex' | |
3 | + | |
4 | +module Cronex | |
5 | + describe ExpressionDescriptor do | |
6 | + | |
7 | + def desc(expression, opts = {}) | |
8 | + opts[:locale] = 'de' | |
9 | + Cronex::ExpressionDescriptor.new(expression, opts).description | |
10 | + end | |
11 | + | |
12 | + let(:opts) { { zero_based_dow: false } } | |
13 | + | |
14 | + it 'every second' do | |
15 | + expect(desc('* * * * * *')).to eq('Jede Sekunde') | |
16 | + end | |
17 | + | |
18 | + it 'every 45 seconds' do | |
19 | + expect(desc('*/45 * * * * *')).to eq('Alle 45 Sekunden') | |
20 | + end | |
21 | + | |
22 | + it 'minute span' do | |
23 | + expect(desc('0-10 11 * * *')).to eq('Jede Minute zwischen 11:00 AM und 11:10 AM') | |
24 | + end | |
25 | + | |
26 | + context 'every minute' do | |
27 | + it 'every minute' do | |
28 | + expect(desc('* * * * *')).to eq('Jede Minute') | |
29 | + end | |
30 | + | |
31 | + it 'every minute */1' do | |
32 | + expect(desc('*/1 * * * *')).to eq('Jede Minute') | |
33 | + end | |
34 | + | |
35 | + it 'every minute 0 0/1' do | |
36 | + expect(desc('0 0/1 * * * ?')).to eq('Jede Minute') | |
37 | + end | |
38 | + end | |
39 | + | |
40 | + context 'every X minutes:' do | |
41 | + it 'every 5 minutes' do | |
42 | + expect(desc('*/5 * * * *')).to eq('Alle 5 Minuten') | |
43 | + end | |
44 | + | |
45 | + it 'every 5 minutes at Midnight' do | |
46 | + expect(desc('*/5 0 * * *')).to eq('Alle 5 Minuten, um 12:00 AM') | |
47 | + end | |
48 | + | |
49 | + it 'every 5 minutes 0 */5' do | |
50 | + expect(desc('0 */5 * * * *')).to eq('Alle 5 Minuten') | |
51 | + end | |
52 | + | |
53 | + it 'every 10 minutes 0 0/10' do | |
54 | + expect(desc('0 0/10 * * * ?')).to eq('Alle 10 Minuten') | |
55 | + end | |
56 | + end | |
57 | + | |
58 | + context 'every hour:' do | |
59 | + it 'every hour 0 0' do | |
60 | + expect(desc('0 0 * * * ?')).to eq('Jede Stunde') | |
61 | + end | |
62 | + | |
63 | + it 'every hour 0 0 0/1' do | |
64 | + expect(desc('0 0 0/1 * * ?')).to eq('Jede Stunde') | |
65 | + end | |
66 | + end | |
67 | + | |
68 | + context 'daily:' do | |
69 | + it 'daily at /\d\d/:/\d\d/' do | |
70 | + expect(desc('30 11 * * *')).to eq('Um 11:30 AM') | |
71 | + end | |
72 | + | |
73 | + it 'daily at /\d/:/\d/' do | |
74 | + expect(desc('9 8 * * *')).to eq('Um 8:09 AM') | |
75 | + end | |
76 | + | |
77 | + it 'daily at /0[89]/:/0[89]/' do | |
78 | + expect(desc('09 08 * * *')).to eq('Um 8:09 AM') | |
79 | + end | |
80 | + | |
81 | + it 'daily at /0[1-7]/ /0[1-7/' do | |
82 | + expect(desc('02 01 * * *')).to eq('Um 1:02 AM') | |
83 | + end | |
84 | + end | |
85 | + | |
86 | + context 'time of day certain days of week:' do | |
87 | + it 'time of day on MON-FRI' do | |
88 | + expect(desc('0 23 ? * MON-FRI')).to eq('Um 11:00 PM, Montag bis Freitag') | |
89 | + end | |
90 | + | |
91 | + it 'time of day on 1-5' do | |
92 | + expect(desc('30 11 * * 1-5')).to eq('Um 11:30 AM, Montag bis Freitag') | |
93 | + end | |
94 | + end | |
95 | + | |
96 | + it 'one month only' do | |
97 | + expect(desc('* * * 3 *')).to eq('Jede Minute, nur in März') | |
98 | + end | |
99 | + | |
100 | + it 'two months only' do | |
101 | + expect(desc('* * * 3,6 *')).to eq('Jede Minute, nur in März und Juni') | |
102 | + end | |
103 | + | |
104 | + it 'two times each afternoon' do | |
105 | + expect(desc('30 14,16 * * *')).to eq('Um 2:30 PM und 4:30 PM') | |
106 | + end | |
107 | + | |
108 | + it 'three times daily' do | |
109 | + expect(desc('30 6,14,16 * * *')).to eq('Um 6:30 AM, 2:30 PM und 4:30 PM') | |
110 | + end | |
111 | + | |
112 | + context 'once a week:' do | |
113 | + it 'once a week 0' do | |
114 | + expect(desc('46 9 * * 0')).to eq('Um 9:46 AM, nur an Sonntag') | |
115 | + end | |
116 | + | |
117 | + it 'once a week SUN' do | |
118 | + expect(desc('46 9 * * SUN')).to eq('Um 9:46 AM, nur an Sonntag') | |
119 | + end | |
120 | + | |
121 | + it 'once a week 7' do | |
122 | + expect(desc('46 9 * * 7')).to eq('Um 9:46 AM, nur an Sonntag') | |
123 | + end | |
124 | + | |
125 | + it 'once a week 1' do | |
126 | + expect(desc('46 9 * * 1')).to eq('Um 9:46 AM, nur an Montag') | |
127 | + end | |
128 | + | |
129 | + it 'once a week 6' do | |
130 | + expect(desc('46 9 * * 6')).to eq('Um 9:46 AM, nur an Samstag') | |
131 | + end | |
132 | + end | |
133 | + | |
134 | + context 'once a week non zero based:' do | |
135 | + it 'once a week 1' do | |
136 | + expect(desc('46 9 * * 1', opts)).to eq('Um 9:46 AM, nur an Sonntag') | |
137 | + end | |
138 | + | |
139 | + it 'once a week SUN' do | |
140 | + expect(desc('46 9 * * SUN', opts)).to eq('Um 9:46 AM, nur an Sonntag') | |
141 | + end | |
142 | + | |
143 | + it 'once a week 2' do | |
144 | + expect(desc('46 9 * * 2', opts)).to eq('Um 9:46 AM, nur an Montag') | |
145 | + end | |
146 | + | |
147 | + it 'once a week 7' do | |
148 | + expect(desc('46 9 * * 7', opts)).to eq('Um 9:46 AM, nur an Samstag') | |
149 | + end | |
150 | + end | |
151 | + | |
152 | + context 'twice a week:' do | |
153 | + it 'twice a week 1,2' do | |
154 | + expect(desc('46 9 * * 1,2')).to eq('Um 9:46 AM, nur an Montag und Dienstag') | |
155 | + end | |
156 | + | |
157 | + it 'twice a week MON,TUE' do | |
158 | + expect(desc('46 9 * * MON,TUE')).to eq('Um 9:46 AM, nur an Montag und Dienstag') | |
159 | + end | |
160 | + | |
161 | + it 'twice a week 0,6' do | |
162 | + expect(desc('46 9 * * 0,6')).to eq('Um 9:46 AM, nur an Sonntag und Samstag') | |
163 | + end | |
164 | + | |
165 | + it 'twice a week 6,7' do | |
166 | + expect(desc('46 9 * * 6,7')).to eq('Um 9:46 AM, nur an Samstag und Sonntag') | |
167 | + end | |
168 | + end | |
169 | + | |
170 | + context 'twice a week non zero based:' do | |
171 | + it 'twice a week 1,2' do | |
172 | + expect(desc('46 9 * * 1,2', opts)).to eq('Um 9:46 AM, nur an Sonntag und Montag') | |
173 | + end | |
174 | + | |
175 | + it 'twice a week SUN,MON' do | |
176 | + expect(desc('46 9 * * SUN,MON', opts)).to eq('Um 9:46 AM, nur an Sonntag und Montag') | |
177 | + end | |
178 | + | |
179 | + it 'twice a week 6,7' do | |
180 | + expect(desc('46 9 * * 6,7', opts)).to eq('Um 9:46 AM, nur an Freitag und Samstag') | |
181 | + end | |
182 | + end | |
183 | + | |
184 | + it 'day of month' do | |
185 | + expect(desc('23 12 15 * *')).to eq('Um 12:23 PM, am 15 Tag des Monats') | |
186 | + end | |
187 | + | |
188 | + it 'day of month with day of week' do | |
189 | + expect(desc('23 12 15 * SUN')).to eq('Um 12:23 PM, am 15 Tag des Monats, nur an Sonntag') | |
190 | + end | |
191 | + | |
192 | + it 'month name' do | |
193 | + expect(desc('23 12 * JAN *')).to eq('Um 12:23 PM, nur in Januar') | |
194 | + end | |
195 | + | |
196 | + it 'day of month with question mark' do | |
197 | + expect(desc('23 12 ? JAN *')).to eq('Um 12:23 PM, nur in Januar') | |
198 | + end | |
199 | + | |
200 | + it 'month name range 2' do | |
201 | + expect(desc('23 12 * JAN-FEB *')).to eq('Um 12:23 PM, Januar bis Februar') | |
202 | + end | |
203 | + | |
204 | + it 'month name range 3' do | |
205 | + expect(desc('23 12 * JAN-MAR *')).to eq('Um 12:23 PM, Januar bis März') | |
206 | + end | |
207 | + | |
208 | + it 'day of week name' do | |
209 | + expect(desc('23 12 * * SUN')).to eq('Um 12:23 PM, nur an Sonntag') | |
210 | + end | |
211 | + | |
212 | + context 'day of week range:' do | |
213 | + it 'day of week range MON-FRI' do | |
214 | + expect(desc('*/5 15 * * MON-FRI')).to eq('Alle 5 Minuten, um 3:00 PM, Montag bis Freitag') | |
215 | + end | |
216 | + | |
217 | + it 'day of week range 0-6' do | |
218 | + expect(desc('*/5 15 * * 0-6')).to eq('Alle 5 Minuten, um 3:00 PM, Sonntag bis Samstag') | |
219 | + end | |
220 | + | |
221 | + it 'day of week range 6-7' do | |
222 | + expect(desc('*/5 15 * * 6-7')).to eq('Alle 5 Minuten, um 3:00 PM, Samstag bis Sonntag') | |
223 | + end | |
224 | + end | |
225 | + | |
226 | + context 'day of week once in month:' do | |
227 | + it 'day of week once MON#3' do | |
228 | + expect(desc('* * * * MON#3')).to eq('Jede Minute, am dritten Montag des Monats') | |
229 | + end | |
230 | + | |
231 | + it 'day of week once 0#3' do | |
232 | + expect(desc('* * * * 0#3')).to eq('Jede Minute, am dritten Sonntag des Monats') | |
233 | + end | |
234 | + end | |
235 | + | |
236 | + context 'last day of week of the month:' do | |
237 | + it 'last day of week 4L' do | |
238 | + expect(desc('* * * * 4L')).to eq('Jede Minute, am letzten Donnerstag des Monats') | |
239 | + end | |
240 | + | |
241 | + it 'last day of week 0L' do | |
242 | + expect(desc('* * * * 0L')).to eq('Jede Minute, am letzten Sonntag des Monats') | |
243 | + end | |
244 | + end | |
245 | + | |
246 | + context 'last day of the month:' do | |
247 | + it 'on the last day of the month' do | |
248 | + expect(desc('*/5 * L JAN *')).to eq('Alle 5 Minuten, am letzten Tag des Monats, nur in Januar') | |
249 | + end | |
250 | + | |
251 | + it 'between a day and last day of the month' do | |
252 | + expect(desc('*/5 * 23-L JAN *')).to eq('Alle 5 Minuten, zwischen Tag 23 und der letzte Tag des Monats, nur in Januar') | |
253 | + end | |
254 | + end | |
255 | + | |
256 | + it 'time of day with seconds' do | |
257 | + expect(desc('30 02 14 * * *')).to eq('Um 2:02:30 PM') | |
258 | + end | |
259 | + | |
260 | + it 'second intervals' do | |
261 | + expect(desc('5-10 * * * * *')).to eq('Sekunden 5 bis 10 vergangene Minute') | |
262 | + end | |
263 | + | |
264 | + it 'second minutes hours intervals' do | |
265 | + expect(desc('5-10 30-35 10-12 * * *')).to eq( | |
266 | + 'Sekunden 5 bis 10 vergangene Minute, Minuten 30 bis 35 nach der vergangenen Stunde, zwischen 10:00 AM und 12:59 PM') | |
267 | + end | |
268 | + | |
269 | + it 'every 5 minutes at 30 seconds' do | |
270 | + expect(desc('30 */5 * * * *')).to eq('Am 30 Sekunden nach der vergangenen Minute, Alle 5 Minuten') | |
271 | + end | |
272 | + | |
273 | + it 'minutes past the hour range' do | |
274 | + expect(desc('0 30 10-13 ? * WED,FRI')).to eq( | |
275 | + 'Um 30 Minuten vergangene Stunde, zwischen 10:00 AM und 1:59 PM, nur an Mittwoch und Freitag') | |
276 | + end | |
277 | + | |
278 | + it 'seconds past the minute interval' do | |
279 | + expect(desc('10 0/5 * * * ?')).to eq('Am 10 Sekunden nach der vergangenen Minute, Alle 5 Minuten') | |
280 | + end | |
281 | + | |
282 | + it 'between with interval' do | |
283 | + expect(desc('2-59/3 1,9,22 11-26 1-6 ?')).to eq( | |
284 | + 'Alle 3 Minuten, Minuten 02 bis 59 nach der vergangenen Stunde, um 1:00 AM, 9:00 AM und 10:00 PM, zwischen Tag 11 und 26 des Monats, Januar bis Juni') | |
285 | + end | |
286 | + | |
287 | + it 'recurring first of month' do | |
288 | + expect(desc('0 0 6 1/1 * ?')).to eq('Um 6:00 AM') | |
289 | + end | |
290 | + | |
291 | + it 'minutes past the hour' do | |
292 | + expect(desc('0 5 0/1 * * ?')).to eq('Um 05 Minuten vergangene Stunde') | |
293 | + end | |
294 | + | |
295 | + it 'every past the hour' do | |
296 | + expect(desc('0 0,5,10,15,20,25,30,35,40,45,50,55 * ? * *')).to eq( | |
297 | + 'Um 00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50 und 55 Minuten vergangene Stunde') | |
298 | + end | |
299 | + | |
300 | + it 'every X minutes past the hour with interval' do | |
301 | + expect(desc('0 0-30/2 17 ? * MON-FRI')).to eq( | |
302 | + 'Alle 2 Minuten, Minuten 00 bis 30 nach der vergangenen Stunde, um 5:00 PM, Montag bis Freitag') | |
303 | + end | |
304 | + | |
305 | + it 'every X days with interval' do | |
306 | + expect(desc('30 7 1-L/2 * *')).to eq('Um 7:30 AM, Alle 2 Tagen, zwischen Tag 1 und der letzte Tag des Monats') | |
307 | + end | |
308 | + | |
309 | + it 'one year only with seconds' do | |
310 | + expect(desc('* * * * * * 2013')).to eq('Jede Sekunde, nur in 2013') | |
311 | + end | |
312 | + | |
313 | + it 'one year only without seconds' do | |
314 | + expect(desc('* * * * * 2013')).to eq('Jede Minute, nur in 2013') | |
315 | + end | |
316 | + | |
317 | + it 'two years only' do | |
318 | + expect(desc('* * * * * 2013,2014')).to eq('Jede Minute, nur in 2013 und 2014') | |
319 | + end | |
320 | + | |
321 | + it 'year range 2' do | |
322 | + expect(desc('23 12 * JAN-FEB * 2013-2014')).to eq('Um 12:23 PM, Januar bis Februar, 2013 bis 2014') | |
323 | + end | |
324 | + | |
325 | + it 'year range 3' do | |
326 | + expect(desc('23 12 * JAN-MAR * 2013-2015')).to eq('Um 12:23 PM, Januar bis März, 2013 bis 2015') | |
327 | + end | |
328 | + | |
329 | + context 'multi part range seconds:' do | |
330 | + it 'multi part range seconds 2,4-5' do | |
331 | + expect(desc('2,4-5 1 * * *')).to eq('Minuten 02,04 bis 05 nach der vergangenen Stunde, um 1:00 AM') | |
332 | + end | |
333 | + | |
334 | + it 'multi part range seconds 2,26-28' do | |
335 | + expect(desc('2,26-28 18 * * *')).to eq('Minuten 02,26 bis 28 nach der vergangenen Stunde, um 6:00 PM') | |
336 | + end | |
337 | + end | |
338 | + | |
339 | + context 'minutes past the hour:' do | |
340 | + it 'minutes past the hour 5,10, midnight hour' do | |
341 | + expect(desc('5,10 0 * * *')).to eq('Um 05 und 10 Minuten vergangene Stunde, um 12:00 AM') | |
342 | + end | |
343 | + | |
344 | + it 'minutes past the hour 5,10' do | |
345 | + expect(desc('5,10 * * * *')).to eq('Um 05 und 10 Minuten vergangene Stunde') | |
346 | + end | |
347 | + | |
348 | + it 'minutes past the hour 5,10 day 2' do | |
349 | + expect(desc('5,10 * 2 * *')).to eq('Um 05 und 10 Minuten vergangene Stunde, am 2 Tag des Monats') | |
350 | + end | |
351 | + | |
352 | + it 'minutes past the hour 5/10 day 2' do | |
353 | + expect(desc('5/10 * 2 * *')).to eq('Alle 10 Minuten, beginnend um 05 Minuten vergangene Stunde, am 2 Tag des Monats') | |
354 | + end | |
355 | + end | |
356 | + | |
357 | + context 'seconds past the minute:' do | |
358 | + it 'seconds past the minute 5,6, midnight hour' do | |
359 | + expect(desc('5,6 0 0 * * *')).to eq('Am 5 und 6 Sekunden nach der vergangenen Minute, um 12:00 AM') | |
360 | + end | |
361 | + | |
362 | + it 'seconds past the minute 5,6' do | |
363 | + expect(desc('5,6 0 * * * *')).to eq('Am 5 und 6 Sekunden nach der vergangenen Minute') | |
364 | + end | |
365 | + | |
366 | + it 'seconds past the minute 5,6 at 1' do | |
367 | + expect(desc('5,6 0 1 * * *')).to eq('Am 5 und 6 Sekunden nach der vergangenen Minute, um 1:00 AM') | |
368 | + end | |
369 | + | |
370 | + it 'seconds past the minute 5,6 day 2' do | |
371 | + expect(desc('5,6 0 * 2 * *')).to eq('Am 5 und 6 Sekunden nach der vergangenen Minute, am 2 Tag des Monats') | |
372 | + end | |
373 | + end | |
374 | + | |
375 | + context 'increments starting at X > 1:' do | |
376 | + it 'second increments' do | |
377 | + expect(desc('5/15 0 * * * *')).to eq('Alle 15 Sekunden, beginnend am 5 Sekunden nach der vergangenen Minute') | |
378 | + end | |
379 | + | |
380 | + it 'minute increments' do | |
381 | + expect(desc('30/10 * * * *')).to eq('Alle 10 Minuten, beginnend um 30 Minuten vergangene Stunde') | |
382 | + end | |
383 | + | |
384 | + it 'hour increments' do | |
385 | + expect(desc('0 30 2/6 * * ?')).to eq('Um 30 Minuten vergangene Stunde, Alle 6 Stunden, beginnend um 2:00 AM') | |
386 | + end | |
387 | + | |
388 | + it 'day of month increments' do | |
389 | + expect(desc('0 30 8 2/7 * *')).to eq('Um 8:30 AM, Alle 7 Tagen, beginnend am 2 Tag des Monats') | |
390 | + end | |
391 | + | |
392 | + it 'day of week increments' do | |
393 | + expect(desc('0 30 11 * * 2/2')).to eq('Um 11:30 AM, jeden 2 Tag der Woche, beginnend an Dienstag') | |
394 | + end | |
395 | + | |
396 | + it 'month increments' do | |
397 | + expect(desc('0 20 10 * 2/3 THU')).to eq('Um 10:20 AM, nur an Donnerstag, Alle 3 Monaten, beginnend in Februar') | |
398 | + end | |
399 | + | |
400 | + it 'year increments' do | |
401 | + expect(desc('0 0 0 1 MAR * 2010/5')).to eq('Um 12:00 AM, am 1 Tag des Monats, nur in März, Alle 5 Jahren, beginnend in 2010') | |
402 | + end | |
403 | + end | |
404 | + end | |
405 | +end | ... | ... |
1 | +++ a/spec/exp_descriptor_en_spec.rb | |
... | ... | @@ -0,0 +1,431 @@ |
1 | +# encoding: utf-8 | |
2 | +require 'cronex' | |
3 | + | |
4 | +module Cronex | |
5 | + describe ExpressionDescriptor do | |
6 | + | |
7 | + def desc(expression, opts = {}) | |
8 | + opts[:locale] = 'en' | |
9 | + Cronex::ExpressionDescriptor.new(expression, opts).description | |
10 | + end | |
11 | + | |
12 | + let(:opts) { { zero_based_dow: false } } | |
13 | + | |
14 | + it 'every second' do | |
15 | + expect(desc('* * * * * *')).to eq('Every second') | |
16 | + end | |
17 | + | |
18 | + it 'every 45 seconds' do | |
19 | + expect(desc('*/45 * * * * *')).to eq('Every 45 seconds') | |
20 | + end | |
21 | + | |
22 | + it 'minute span' do | |
23 | + expect(desc('0-10 11 * * *')).to eq('Every minute between 11:00 AM and 11:10 AM') | |
24 | + end | |
25 | + | |
26 | + context 'every minute' do | |
27 | + it 'every minute' do | |
28 | + expect(desc('* * * * *')).to eq('Every minute') | |
29 | + end | |
30 | + | |
31 | + it 'every minute */1' do | |
32 | + expect(desc('*/1 * * * *')).to eq('Every minute') | |
33 | + end | |
34 | + | |
35 | + it 'every minute 0 0/1' do | |
36 | + expect(desc('0 0/1 * * * ?')).to eq('Every minute') | |
37 | + end | |
38 | + end | |
39 | + | |
40 | + context 'every X minutes:' do | |
41 | + it 'every 5 minutes' do | |
42 | + expect(desc('*/5 * * * *')).to eq('Every 5 minutes') | |
43 | + end | |
44 | + | |
45 | + it 'every 5 minutes at Midnight' do | |
46 | + expect(desc('*/5 0 * * *')).to eq('Every 5 minutes, at 12:00 AM') | |
47 | + end | |
48 | + | |
49 | + it 'every 5 minutes 0 */5' do | |
50 | + expect(desc('0 */5 * * * *')).to eq('Every 5 minutes') | |
51 | + end | |
52 | + | |
53 | + it 'every 10 minutes 0 0/10' do | |
54 | + expect(desc('0 0/10 * * * ?')).to eq('Every 10 minutes') | |
55 | + end | |
56 | + end | |
57 | + | |
58 | + context 'every hour:' do | |
59 | + it 'every hour 0 0' do | |
60 | + expect(desc('0 0 * * * ?')).to eq('Every hour') | |
61 | + end | |
62 | + | |
63 | + it 'every hour 0 0 0/1' do | |
64 | + expect(desc('0 0 0/1 * * ?')).to eq('Every hour') | |
65 | + end | |
66 | + end | |
67 | + | |
68 | + context 'daily:' do | |
69 | + it 'daily at /\d\d/:/\d\d/' do | |
70 | + expect(desc('30 11 * * *')).to eq('At 11:30 AM') | |
71 | + end | |
72 | + | |
73 | + it 'daily at /\d/:/\d/' do | |
74 | + expect(desc('9 8 * * *')).to eq('At 8:09 AM') | |
75 | + end | |
76 | + | |
77 | + it 'daily at /0[89]/:/0[89]/' do | |
78 | + expect(desc('09 08 * * *')).to eq('At 8:09 AM') | |
79 | + end | |
80 | + | |
81 | + it 'daily at /0[1-7]/ /0[1-7/' do | |
82 | + expect(desc('02 01 * * *')).to eq('At 1:02 AM') | |
83 | + end | |
84 | + end | |
85 | + | |
86 | + context 'time of day certain days of week:' do | |
87 | + it 'time of day on MON-FRI' do | |
88 | + expect(desc('0 23 ? * MON-FRI')).to eq('At 11:00 PM, Monday through Friday') | |
89 | + end | |
90 | + | |
91 | + it 'time of day on 1-5' do | |
92 | + expect(desc('30 11 * * 1-5')).to eq('At 11:30 AM, Monday through Friday') | |
93 | + end | |
94 | + end | |
95 | + | |
96 | + it 'one month only' do | |
97 | + expect(desc('* * * 3 *')).to eq('Every minute, only in March') | |
98 | + end | |
99 | + | |
100 | + it 'two months only' do | |
101 | + expect(desc('* * * 3,6 *')).to eq('Every minute, only in March and June') | |
102 | + end | |
103 | + | |
104 | + it 'two times each afternoon' do | |
105 | + expect(desc('30 14,16 * * *')).to eq('At 2:30 PM and 4:30 PM') | |
106 | + end | |
107 | + | |
108 | + it 'three times daily' do | |
109 | + expect(desc('30 6,14,16 * * *')).to eq('At 6:30 AM, 2:30 PM and 4:30 PM') | |
110 | + end | |
111 | + | |
112 | + context 'once a week:' do | |
113 | + it 'once a week 0' do | |
114 | + expect(desc('46 9 * * 0')).to eq('At 9:46 AM, only on Sunday') | |
115 | + end | |
116 | + | |
117 | + it 'once a week SUN' do | |
118 | + expect(desc('46 9 * * SUN')).to eq('At 9:46 AM, only on Sunday') | |
119 | + end | |
120 | + | |
121 | + it 'once a week 7' do | |
122 | + expect(desc('46 9 * * 7')).to eq('At 9:46 AM, only on Sunday') | |
123 | + end | |
124 | + | |
125 | + it 'once a week 1' do | |
126 | + expect(desc('46 9 * * 1')).to eq('At 9:46 AM, only on Monday') | |
127 | + end | |
128 | + | |
129 | + it 'once a week 6' do | |
130 | + expect(desc('46 9 * * 6')).to eq('At 9:46 AM, only on Saturday') | |
131 | + end | |
132 | + end | |
133 | + | |
134 | + context 'once a week non zero based:' do | |
135 | + it 'once a week 1' do | |
136 | + expect(desc('46 9 * * 1', opts)).to eq('At 9:46 AM, only on Sunday') | |
137 | + end | |
138 | + | |
139 | + it 'once a week SUN' do | |
140 | + expect(desc('46 9 * * SUN', opts)).to eq('At 9:46 AM, only on Sunday') | |
141 | + end | |
142 | + | |
143 | + it 'once a week 2' do | |
144 | + expect(desc('46 9 * * 2', opts)).to eq('At 9:46 AM, only on Monday') | |
145 | + end | |
146 | + | |
147 | + it 'once a week 7' do | |
148 | + expect(desc('46 9 * * 7', opts)).to eq('At 9:46 AM, only on Saturday') | |
149 | + end | |
150 | + end | |
151 | + | |
152 | + context 'twice a week:' do | |
153 | + it 'twice a week 1,2' do | |
154 | + expect(desc('46 9 * * 1,2')).to eq('At 9:46 AM, only on Monday and Tuesday') | |
155 | + end | |
156 | + | |
157 | + it 'twice a week MON,TUE' do | |
158 | + expect(desc('46 9 * * MON,TUE')).to eq('At 9:46 AM, only on Monday and Tuesday') | |
159 | + end | |
160 | + | |
161 | + it 'twice a week 0,6' do | |
162 | + expect(desc('46 9 * * 0,6')).to eq('At 9:46 AM, only on Sunday and Saturday') | |
163 | + end | |
164 | + | |
165 | + it 'twice a week 6,7' do | |
166 | + expect(desc('46 9 * * 6,7')).to eq('At 9:46 AM, only on Saturday and Sunday') | |
167 | + end | |
168 | + end | |
169 | + | |
170 | + context 'twice a week non zero based:' do | |
171 | + it 'twice a week 1,2' do | |
172 | + expect(desc('46 9 * * 1,2', opts)).to eq('At 9:46 AM, only on Sunday and Monday') | |
173 | + end | |
174 | + | |
175 | + it 'twice a week SUN,MON' do | |
176 | + expect(desc('46 9 * * SUN,MON', opts)).to eq('At 9:46 AM, only on Sunday and Monday') | |
177 | + end | |
178 | + | |
179 | + it 'twice a week 6,7' do | |
180 | + expect(desc('46 9 * * 6,7', opts)).to eq('At 9:46 AM, only on Friday and Saturday') | |
181 | + end | |
182 | + end | |
183 | + | |
184 | + it 'day of month' do | |
185 | + expect(desc('23 12 15 * *')).to eq('At 12:23 PM, on day 15 of the month') | |
186 | + end | |
187 | + | |
188 | + it 'day of month with day of week' do | |
189 | + expect(desc('23 12 15 * SUN')).to eq('At 12:23 PM, on day 15 of the month, only on Sunday') | |
190 | + end | |
191 | + | |
192 | + it 'month name' do | |
193 | + expect(desc('23 12 * JAN *')).to eq('At 12:23 PM, only in January') | |
194 | + end | |
195 | + | |
196 | + it 'day of month with question mark' do | |
197 | + expect(desc('23 12 ? JAN *')).to eq('At 12:23 PM, only in January') | |
198 | + end | |
199 | + | |
200 | + it 'month name range 2' do | |
201 | + expect(desc('23 12 * JAN-FEB *')).to eq('At 12:23 PM, January through February') | |
202 | + end | |
203 | + | |
204 | + it 'month name range 3' do | |
205 | + expect(desc('23 12 * JAN-MAR *')).to eq('At 12:23 PM, January through March') | |
206 | + end | |
207 | + | |
208 | + it 'day of week name' do | |
209 | + expect(desc('23 12 * * SUN')).to eq('At 12:23 PM, only on Sunday') | |
210 | + end | |
211 | + | |
212 | + context 'day of week range:' do | |
213 | + it 'day of week range MON-FRI' do | |
214 | + expect(desc('*/5 15 * * MON-FRI')).to eq('Every 5 minutes, at 3:00 PM, Monday through Friday') | |
215 | + end | |
216 | + | |
217 | + it 'day of week range 0-6' do | |
218 | + expect(desc('*/5 15 * * 0-6')).to eq('Every 5 minutes, at 3:00 PM, Sunday through Saturday') | |
219 | + end | |
220 | + | |
221 | + it 'day of week range 6-7' do | |
222 | + expect(desc('*/5 15 * * 6-7')).to eq('Every 5 minutes, at 3:00 PM, Saturday through Sunday') | |
223 | + end | |
224 | + end | |
225 | + | |
226 | + context 'day of week once in month:' do | |
227 | + it 'day of week once MON#3' do | |
228 | + expect(desc('* * * * MON#3')).to eq('Every minute, on the third Monday of the month') | |
229 | + end | |
230 | + | |
231 | + it 'day of week once 0#3' do | |
232 | + expect(desc('* * * * 0#3')).to eq('Every minute, on the third Sunday of the month') | |
233 | + end | |
234 | + end | |
235 | + | |
236 | + context 'last day of week of the month:' do | |
237 | + it 'last day of week 4L' do | |
238 | + expect(desc('* * * * 4L')).to eq('Every minute, on the last Thursday of the month') | |
239 | + end | |
240 | + | |
241 | + it 'last day of week 0L' do | |
242 | + expect(desc('* * * * 0L')).to eq('Every minute, on the last Sunday of the month') | |
243 | + end | |
244 | + end | |
245 | + | |
246 | + context 'last day of the month:' do | |
247 | + it 'on the last day of the month' do | |
248 | + expect(desc('*/5 * L JAN *')).to eq('Every 5 minutes, on the last day of the month, only in January') | |
249 | + end | |
250 | + | |
251 | + it 'between a day and last day of the month' do | |
252 | + expect(desc('*/5 * 23-L JAN *')).to eq('Every 5 minutes, between day 23 and the last day of the month, only in January') | |
253 | + end | |
254 | + end | |
255 | + | |
256 | + it 'time of day with seconds' do | |
257 | + expect(desc('30 02 14 * * *')).to eq('At 2:02:30 PM') | |
258 | + end | |
259 | + | |
260 | + it 'second intervals' do | |
261 | + expect(desc('5-10 * * * * *')).to eq('Seconds 5 through 10 past the minute') | |
262 | + end | |
263 | + | |
264 | + it 'second minutes hours intervals' do | |
265 | + expect(desc('5-10 30-35 10-12 * * *')).to eq( | |
266 | + 'Seconds 5 through 10 past the minute, minutes 30 through 35 past the hour, between 10:00 AM and 12:59 PM') | |
267 | + end | |
268 | + | |
269 | + it 'every 5 minutes at 30 seconds' do | |
270 | + expect(desc('30 */5 * * * *')).to eq('At 30 seconds past the minute, every 5 minutes') | |
271 | + end | |
272 | + | |
273 | + it 'minutes past the hour range' do | |
274 | + expect(desc('0 30 10-13 ? * WED,FRI')).to eq( | |
275 | + 'At 30 minutes past the hour, between 10:00 AM and 1:59 PM, only on Wednesday and Friday') | |
276 | + end | |
277 | + | |
278 | + it 'seconds past the minute interval' do | |
279 | + expect(desc('10 0/5 * * * ?')).to eq('At 10 seconds past the minute, every 5 minutes') | |
280 | + end | |
281 | + | |
282 | + it 'between with interval' do | |
283 | + expect(desc('2-59/3 1,9,22 11-26 1-6 ?')).to eq( | |
284 | + 'Every 3 minutes, minutes 02 through 59 past the hour, at 1:00 AM, 9:00 AM and 10:00 PM, between day 11 and 26 of the month, January through June') | |
285 | + end | |
286 | + | |
287 | + it 'recurring first of month' do | |
288 | + expect(desc('0 0 6 1/1 * ?')).to eq('At 6:00 AM') | |
289 | + end | |
290 | + | |
291 | + it 'minutes past the hour' do | |
292 | + expect(desc('0 5 0/1 * * ?')).to eq('At 05 minutes past the hour') | |
293 | + end | |
294 | + | |
295 | + it 'every past the hour' do | |
296 | + expect(desc('0 0,5,10,15,20,25,30,35,40,45,50,55 * ? * *')).to eq( | |
297 | + 'At 00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50 and 55 minutes past the hour') | |
298 | + end | |
299 | + | |
300 | + it 'every X minutes past the hour with interval' do | |
301 | + expect(desc('0 0-30/2 17 ? * MON-FRI')).to eq( | |
302 | + 'Every 2 minutes, minutes 00 through 30 past the hour, at 5:00 PM, Monday through Friday') | |
303 | + end | |
304 | + | |
305 | + it 'every X days with interval' do | |
306 | + expect(desc('30 7 1-L/2 * *')).to eq('At 7:30 AM, every 2 days, between day 1 and the last day of the month') | |
307 | + end | |
308 | + | |
309 | + it 'one year only with seconds' do | |
310 | + expect(desc('* * * * * * 2013')).to eq('Every second, only in 2013') | |
311 | + end | |
312 | + | |
313 | + it 'one year only without seconds' do | |
314 | + expect(desc('* * * * * 2013')).to eq('Every minute, only in 2013') | |
315 | + end | |
316 | + | |
317 | + it 'two years only' do | |
318 | + expect(desc('* * * * * 2013,2014')).to eq('Every minute, only in 2013 and 2014') | |
319 | + end | |
320 | + | |
321 | + it 'year range 2' do | |
322 | + expect(desc('23 12 * JAN-FEB * 2013-2014')).to eq('At 12:23 PM, January through February, 2013 through 2014') | |
323 | + end | |
324 | + | |
325 | + it 'year range 3' do | |
326 | + expect(desc('23 12 * JAN-MAR * 2013-2015')).to eq('At 12:23 PM, January through March, 2013 through 2015') | |
327 | + end | |
328 | + | |
329 | + context 'multi part range seconds:' do | |
330 | + it 'multi part range seconds 2,4-5' do | |
331 | + expect(desc('2,4-5 1 * * *')).to eq('Minutes 02,04 through 05 past the hour, at 1:00 AM') | |
332 | + end | |
333 | + | |
334 | + it 'multi part range seconds 2,26-28' do | |
335 | + expect(desc('2,26-28 18 * * *')).to eq('Minutes 02,26 through 28 past the hour, at 6:00 PM') | |
336 | + end | |
337 | + end | |
338 | + | |
339 | + context 'minutes past the hour:' do | |
340 | + it 'minutes past the hour 5,10, midnight hour' do | |
341 | + expect(desc('5,10 0 * * *')).to eq('At 05 and 10 minutes past the hour, at 12:00 AM') | |
342 | + end | |
343 | + | |
344 | + it 'minutes past the hour 5,10' do | |
345 | + expect(desc('5,10 * * * *')).to eq('At 05 and 10 minutes past the hour') | |
346 | + end | |
347 | + | |
348 | + it 'minutes past the hour 5,10 day 2' do | |
349 | + expect(desc('5,10 * 2 * *')).to eq('At 05 and 10 minutes past the hour, on day 2 of the month') | |
350 | + end | |
351 | + | |
352 | + it 'minutes past the hour 5/10 day 2' do | |
353 | + expect(desc('5/10 * 2 * *')).to eq('Every 10 minutes, starting at 05 minutes past the hour, on day 2 of the month') | |
354 | + end | |
355 | + end | |
356 | + | |
357 | + context 'seconds past the minute:' do | |
358 | + it 'seconds past the minute 5,6, midnight hour' do | |
359 | + expect(desc('5,6 0 0 * * *')).to eq('At 5 and 6 seconds past the minute, at 12:00 AM') | |
360 | + end | |
361 | + | |
362 | + it 'seconds past the minute 5,6' do | |
363 | + expect(desc('5,6 0 * * * *')).to eq('At 5 and 6 seconds past the minute') | |
364 | + end | |
365 | + | |
366 | + it 'seconds past the minute 5,6 at 1' do | |
367 | + expect(desc('5,6 0 1 * * *')).to eq('At 5 and 6 seconds past the minute, at 1:00 AM') | |
368 | + end | |
369 | + | |
370 | + it 'seconds past the minute 5,6 day 2' do | |
371 | + expect(desc('5,6 0 * 2 * *')).to eq('At 5 and 6 seconds past the minute, on day 2 of the month') | |
372 | + end | |
373 | + end | |
374 | + | |
375 | + context 'increments starting at X > 1:' do | |
376 | + it 'second increments' do | |
377 | + expect(desc('5/15 0 * * * *')).to eq('Every 15 seconds, starting at 5 seconds past the minute') | |
378 | + end | |
379 | + | |
380 | + it 'minute increments' do | |
381 | + expect(desc('30/10 * * * *')).to eq('Every 10 minutes, starting at 30 minutes past the hour') | |
382 | + end | |
383 | + | |
384 | + it 'hour increments' do | |
385 | + expect(desc('0 30 2/6 * * ?')).to eq('At 30 minutes past the hour, every 6 hours, starting at 2:00 AM') | |
386 | + end | |
387 | + | |
388 | + it 'day of month increments' do | |
389 | + expect(desc('0 30 8 2/7 * *')).to eq('At 8:30 AM, every 7 days, starting on day 2 of the month') | |
390 | + end | |
391 | + | |
392 | + it 'day of week increments' do | |
393 | + expect(desc('0 30 11 * * 2/2')).to eq('At 11:30 AM, every 2 days of the week, starting on Tuesday') | |
394 | + end | |
395 | + | |
396 | + it 'month increments' do | |
397 | + expect(desc('0 20 10 * 2/3 THU')).to eq('At 10:20 AM, only on Thursday, every 3 months, starting in February') | |
398 | + end | |
399 | + | |
400 | + it 'year increments' do | |
401 | + expect(desc('0 0 0 1 MAR * 2010/5')).to eq('At 12:00 AM, on day 1 of the month, only in March, every 5 years, starting in 2010') | |
402 | + end | |
403 | + end | |
404 | + | |
405 | + context 'strict_quartz' do | |
406 | + it '5 part cron fails' do | |
407 | + expect { desc('* * * * *', strict_quartz: true) }.to raise_error(Cronex::ExpressionError) | |
408 | + end | |
409 | + end | |
410 | + | |
411 | + context 'timezone' do | |
412 | + it 'minute span' do | |
413 | + tz = TZInfo::Timezone.get('America/Los_Angeles') | |
414 | + hour = tz.period_for_local(Time.now).zone_identifier.to_s == 'PDT' ? 4 : 3 | |
415 | + expect(desc('0-10 11 * * *', timezone: 'America/Los_Angeles')).to eq("Every minute between #{hour}:00 AM and #{hour}:10 AM") | |
416 | + end | |
417 | + | |
418 | + it 'twice a day' do | |
419 | + tz = TZInfo::Timezone.get('America/Los_Angeles') | |
420 | + hour = tz.period_for_local(Time.now).zone_identifier.to_s == 'PDT' ? 5 : 4 | |
421 | + expect(desc('0 0,12 * * *', timezone: 'America/Los_Angeles')).to eq("At #{hour}:00 PM and #{hour}:00 AM") | |
422 | + end | |
423 | + | |
424 | + it 'ahead of GMT' do | |
425 | + tz = TZInfo::Timezone.get('Europe/Vienna') | |
426 | + hour = tz.period_for_local(Time.now).zone_identifier.to_s == 'CEST' ? 1 : 12 | |
427 | + expect(desc('0-10 11 * * *', timezone: 'Europe/Vienna')).to eq("Every minute between #{hour}:00 PM and #{hour}:10 PM") | |
428 | + end | |
429 | + end | |
430 | + end | |
431 | +end | ... | ... |
1 | +++ a/spec/exp_descriptor_fr_spec.rb | |
... | ... | @@ -0,0 +1,405 @@ |
1 | +# encoding: utf-8 | |
2 | +require 'cronex' | |
3 | + | |
4 | +module Cronex | |
5 | + describe ExpressionDescriptor do | |
6 | + | |
7 | + def desc(expression, opts = {}) | |
8 | + opts[:locale] = 'fr' | |
9 | + Cronex::ExpressionDescriptor.new(expression, opts).description | |
10 | + end | |
11 | + | |
12 | + let(:opts) { { zero_based_dow: false } } | |
13 | + | |
14 | + it 'every second' do | |
15 | + expect(desc('* * * * * *')).to eq('Chaque seconde') | |
16 | + end | |
17 | + | |
18 | + it 'every 45 seconds' do | |
19 | + expect(desc('*/45 * * * * *')).to eq('Toutes les 45 secondes') | |
20 | + end | |
21 | + | |
22 | + it 'minute span' do | |
23 | + expect(desc('0-10 11 * * *')).to eq('Chaque minute entre 11:00 AM et 11:10 AM') | |
24 | + end | |
25 | + | |
26 | + context 'every minute' do | |
27 | + it 'every minute' do | |
28 | + expect(desc('* * * * *')).to eq('Chaque minute') | |
29 | + end | |
30 | + | |
31 | + it 'every minute */1' do | |
32 | + expect(desc('*/1 * * * *')).to eq('Chaque minute') | |
33 | + end | |
34 | + | |
35 | + it 'every minute 0 0/1' do | |
36 | + expect(desc('0 0/1 * * * ?')).to eq('Chaque minute') | |
37 | + end | |
38 | + end | |
39 | + | |
40 | + context 'every X minutes:' do | |
41 | + it 'every 5 minutes' do | |
42 | + expect(desc('*/5 * * * *')).to eq('Tous les 5 minutes') | |
43 | + end | |
44 | + | |
45 | + it 'every 5 minutes at Midnight' do | |
46 | + expect(desc('*/5 0 * * *')).to eq('Tous les 5 minutes, à 12:00 AM') | |
47 | + end | |
48 | + | |
49 | + it 'every 5 minutes 0 */5' do | |
50 | + expect(desc('0 */5 * * * *')).to eq('Tous les 5 minutes') | |
51 | + end | |
52 | + | |
53 | + it 'every 10 minutes 0 0/10' do | |
54 | + expect(desc('0 0/10 * * * ?')).to eq('Tous les 10 minutes') | |
55 | + end | |
56 | + end | |
57 | + | |
58 | + context 'every hour:' do | |
59 | + it 'every hour 0 0' do | |
60 | + expect(desc('0 0 * * * ?')).to eq('Chaque heure') | |
61 | + end | |
62 | + | |
63 | + it 'every hour 0 0 0/1' do | |
64 | + expect(desc('0 0 0/1 * * ?')).to eq('Chaque heure') | |
65 | + end | |
66 | + end | |
67 | + | |
68 | + context 'daily:' do | |
69 | + it 'daily at /\d\d/:/\d\d/' do | |
70 | + expect(desc('30 11 * * *')).to eq('À 11:30 AM') | |
71 | + end | |
72 | + | |
73 | + it 'daily at /\d/:/\d/' do | |
74 | + expect(desc('9 8 * * *')).to eq('À 8:09 AM') | |
75 | + end | |
76 | + | |
77 | + it 'daily at /0[89]/:/0[89]/' do | |
78 | + expect(desc('09 08 * * *')).to eq('À 8:09 AM') | |
79 | + end | |
80 | + | |
81 | + it 'daily at /0[1-7]/ /0[1-7/' do | |
82 | + expect(desc('02 01 * * *')).to eq('À 1:02 AM') | |
83 | + end | |
84 | + end | |
85 | + | |
86 | + context 'time of day certain days of week:' do | |
87 | + it 'time of day on MON-FRI' do | |
88 | + expect(desc('0 23 ? * MON-FRI')).to eq('À 11:00 PM, lundi à vendredi') | |
89 | + end | |
90 | + | |
91 | + it 'time of day on 1-5' do | |
92 | + expect(desc('30 11 * * 1-5')).to eq('À 11:30 AM, lundi à vendredi') | |
93 | + end | |
94 | + end | |
95 | + | |
96 | + it 'one month only' do | |
97 | + expect(desc('* * * 3 *')).to eq('Chaque minute, seulement en mars') | |
98 | + end | |
99 | + | |
100 | + it 'two months only' do | |
101 | + expect(desc('* * * 3,6 *')).to eq("Chaque minute, seulement en mars et juin") | |
102 | + end | |
103 | + | |
104 | + it 'two times each afternoon' do | |
105 | + expect(desc('30 14,16 * * *')).to eq("À 2:30 PM et 4:30 PM") | |
106 | + end | |
107 | + | |
108 | + it 'three times daily' do | |
109 | + expect(desc('30 6,14,16 * * *')).to eq('À 6:30 AM, 2:30 PM et 4:30 PM') | |
110 | + end | |
111 | + | |
112 | + context 'once a week:' do | |
113 | + it 'once a week 0' do | |
114 | + expect(desc('46 9 * * 0')).to eq('À 9:46 AM, seulement le dimanche') | |
115 | + end | |
116 | + | |
117 | + it 'once a week SUN' do | |
118 | + expect(desc('46 9 * * SUN')).to eq('À 9:46 AM, seulement le dimanche') | |
119 | + end | |
120 | + | |
121 | + it 'once a week 7' do | |
122 | + expect(desc('46 9 * * 7')).to eq('À 9:46 AM, seulement le dimanche') | |
123 | + end | |
124 | + | |
125 | + it 'once a week 1' do | |
126 | + expect(desc('46 9 * * 1')).to eq('À 9:46 AM, seulement le lundi') | |
127 | + end | |
128 | + | |
129 | + it 'once a week 6' do | |
130 | + expect(desc('46 9 * * 6')).to eq('À 9:46 AM, seulement le samedi') | |
131 | + end | |
132 | + end | |
133 | + | |
134 | + context 'once a week non zero based:' do | |
135 | + it 'once a week 1' do | |
136 | + expect(desc('46 9 * * 1', opts)).to eq('À 9:46 AM, seulement le dimanche') | |
137 | + end | |
138 | + | |
139 | + it 'once a week SUN' do | |
140 | + expect(desc('46 9 * * SUN', opts)).to eq('À 9:46 AM, seulement le dimanche') | |
141 | + end | |
142 | + | |
143 | + it 'once a week 2' do | |
144 | + expect(desc('46 9 * * 2', opts)).to eq('À 9:46 AM, seulement le lundi') | |
145 | + end | |
146 | + | |
147 | + it 'once a week 7' do | |
148 | + expect(desc('46 9 * * 7', opts)).to eq('À 9:46 AM, seulement le samedi') | |
149 | + end | |
150 | + end | |
151 | + | |
152 | + context 'twice a week:' do | |
153 | + it 'twice a week 1,2' do | |
154 | + expect(desc('46 9 * * 1,2')).to eq('À 9:46 AM, seulement le lundi et mardi') | |
155 | + end | |
156 | + | |
157 | + it 'twice a week MON,TUE' do | |
158 | + expect(desc('46 9 * * MON,TUE')).to eq('À 9:46 AM, seulement le lundi et mardi') | |
159 | + end | |
160 | + | |
161 | + it 'twice a week 0,6' do | |
162 | + expect(desc('46 9 * * 0,6')).to eq('À 9:46 AM, seulement le dimanche et samedi') | |
163 | + end | |
164 | + | |
165 | + it 'twice a week 6,7' do | |
166 | + expect(desc('46 9 * * 6,7')).to eq('À 9:46 AM, seulement le samedi et dimanche') | |
167 | + end | |
168 | + end | |
169 | + | |
170 | + context 'twice a week non zero based:' do | |
171 | + it 'twice a week 1,2' do | |
172 | + expect(desc('46 9 * * 1,2', opts)).to eq('À 9:46 AM, seulement le dimanche et lundi') | |
173 | + end | |
174 | + | |
175 | + it 'twice a week SUN,MON' do | |
176 | + expect(desc('46 9 * * SUN,MON', opts)).to eq('À 9:46 AM, seulement le dimanche et lundi') | |
177 | + end | |
178 | + | |
179 | + it 'twice a week 6,7' do | |
180 | + expect(desc('46 9 * * 6,7', opts)).to eq('À 9:46 AM, seulement le vendredi et samedi') | |
181 | + end | |
182 | + end | |
183 | + | |
184 | + it 'day of month' do | |
185 | + expect(desc('23 12 15 * *')).to eq('À 12:23 PM, le 15 de chaque mois') | |
186 | + end | |
187 | + | |
188 | + it 'day of month with day of week' do | |
189 | + expect(desc('23 12 15 * SUN')).to eq('À 12:23 PM, le 15 de chaque mois, seulement le dimanche') | |
190 | + end | |
191 | + | |
192 | + it 'month name' do | |
193 | + expect(desc('23 12 * JAN *')).to eq('À 12:23 PM, seulement en janvier') | |
194 | + end | |
195 | + | |
196 | + it 'day of month with question mark' do | |
197 | + expect(desc('23 12 ? JAN *')).to eq('À 12:23 PM, seulement en janvier') | |
198 | + end | |
199 | + | |
200 | + it 'month name range 2' do | |
201 | + expect(desc('23 12 * JAN-FEB *')).to eq('À 12:23 PM, janvier à février') | |
202 | + end | |
203 | + | |
204 | + it 'month name range 3' do | |
205 | + expect(desc('23 12 * JAN-MAR *')).to eq('À 12:23 PM, janvier à mars') | |
206 | + end | |
207 | + | |
208 | + it 'day of week name' do | |
209 | + expect(desc('23 12 * * SUN')).to eq('À 12:23 PM, seulement le dimanche') | |
210 | + end | |
211 | + | |
212 | + context 'day of week range:' do | |
213 | + it 'day of week range MON-FRI' do | |
214 | + expect(desc('*/5 15 * * MON-FRI')).to eq('Tous les 5 minutes, à 3:00 PM, lundi à vendredi') | |
215 | + end | |
216 | + | |
217 | + it 'day of week range 0-6' do | |
218 | + expect(desc('*/5 15 * * 0-6')).to eq('Tous les 5 minutes, à 3:00 PM, dimanche à samedi') | |
219 | + end | |
220 | + | |
221 | + it 'day of week range 6-7' do | |
222 | + expect(desc('*/5 15 * * 6-7')).to eq('Tous les 5 minutes, à 3:00 PM, samedi à dimanche') | |
223 | + end | |
224 | + end | |
225 | + | |
226 | + context 'day of week once in month:' do | |
227 | + it 'day of week once MON#3' do | |
228 | + expect(desc('* * * * MON#3')).to eq('Chaque minute, le troisième lundi du mois') | |
229 | + end | |
230 | + | |
231 | + it 'day of week once 0#3' do | |
232 | + expect(desc('* * * * 0#3')).to eq('Chaque minute, le troisième dimanche du mois') | |
233 | + end | |
234 | + end | |
235 | + | |
236 | + context 'last day of week of the month:' do | |
237 | + it 'last day of week 4L' do | |
238 | + expect(desc('* * * * 4L')).to eq('Chaque minute, le dernier jeudi du mois') | |
239 | + end | |
240 | + | |
241 | + it 'last day of week 0L' do | |
242 | + expect(desc('* * * * 0L')).to eq('Chaque minute, le dernier dimanche du mois') | |
243 | + end | |
244 | + end | |
245 | + | |
246 | + context 'last day of the month:' do | |
247 | + it 'on the last day of the month' do | |
248 | + expect(desc('*/5 * L JAN *')).to eq('Tous les 5 minutes, le dernier jour du mois, seulement en janvier') | |
249 | + end | |
250 | + | |
251 | + it 'between a day and last day of the month' do | |
252 | + expect(desc('*/5 * 23-L JAN *')).to eq('Tous les 5 minutes, entre le jour 23 et le dernier jour du mois, seulement en janvier') | |
253 | + end | |
254 | + end | |
255 | + | |
256 | + it 'time of day with seconds' do | |
257 | + expect(desc('30 02 14 * * *')).to eq('À 2:02:30 PM') | |
258 | + end | |
259 | + | |
260 | + it 'second intervals' do | |
261 | + expect(desc('5-10 * * * * *')).to eq('Secondes 5 à 10 après la minute') | |
262 | + end | |
263 | + | |
264 | + it 'second minutes hours intervals' do | |
265 | + expect(desc('5-10 30-35 10-12 * * *')).to eq( | |
266 | + "Secondes 5 à 10 après la minute, minutes 30 à 35 après l'heure, entre 10:00 AM et 12:59 PM") | |
267 | + end | |
268 | + | |
269 | + it 'every 5 minutes at 30 seconds' do | |
270 | + expect(desc('30 */5 * * * *')).to eq('À 30 secondes après la minute, tous les 5 minutes') | |
271 | + end | |
272 | + | |
273 | + it 'minutes past the hour range' do | |
274 | + expect(desc('0 30 10-13 ? * WED,FRI')).to eq( | |
275 | + "À 30 minutes après l'heure, entre 10:00 AM et 1:59 PM, seulement le mercredi et vendredi") | |
276 | + end | |
277 | + | |
278 | + it 'seconds past the minute interval' do | |
279 | + expect(desc('10 0/5 * * * ?')).to eq('À 10 secondes après la minute, tous les 5 minutes') | |
280 | + end | |
281 | + | |
282 | + it 'between with interval' do | |
283 | + expect(desc('2-59/3 1,9,22 11-26 1-6 ?')).to eq( | |
284 | + "Tous les 3 minutes, minutes 02 à 59 après l'heure, à 1:00 AM, 9:00 AM et 10:00 PM, entre le jour 11 et le 26 du mois, janvier à juin") | |
285 | + end | |
286 | + | |
287 | + it 'recurring first of month' do | |
288 | + expect(desc('0 0 6 1/1 * ?')).to eq('À 6:00 AM') | |
289 | + end | |
290 | + | |
291 | + it 'minutes past the hour' do | |
292 | + expect(desc('0 5 0/1 * * ?')).to eq("À 05 minutes après l'heure") | |
293 | + end | |
294 | + | |
295 | + it 'every past the hour' do | |
296 | + expect(desc('0 0,5,10,15,20,25,30,35,40,45,50,55 * ? * *')).to eq( | |
297 | + "À 00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50 et 55 minutes après l'heure") | |
298 | + end | |
299 | + | |
300 | + it 'every X minutes past the hour with interval' do | |
301 | + expect(desc('0 0-30/2 17 ? * MON-FRI')).to eq( | |
302 | + "Tous les 2 minutes, minutes 00 à 30 après l'heure, à 5:00 PM, lundi à vendredi") | |
303 | + end | |
304 | + | |
305 | + it 'every X days with interval' do | |
306 | + expect(desc('30 7 1-L/2 * *')).to eq('À 7:30 AM, tous les 2 jours, entre le jour 1 et le dernier jour du mois') | |
307 | + end | |
308 | + | |
309 | + it 'one year only with seconds' do | |
310 | + expect(desc('* * * * * * 2013')).to eq('Chaque seconde, seulement en 2013') | |
311 | + end | |
312 | + | |
313 | + it 'one year only without seconds' do | |
314 | + expect(desc('* * * * * 2013')).to eq('Chaque minute, seulement en 2013') | |
315 | + end | |
316 | + | |
317 | + it 'two years only' do | |
318 | + expect(desc('* * * * * 2013,2014')).to eq('Chaque minute, seulement en 2013 et 2014') | |
319 | + end | |
320 | + | |
321 | + it 'year range 2' do | |
322 | + expect(desc('23 12 * JAN-FEB * 2013-2014')).to eq('À 12:23 PM, janvier à février, 2013 à 2014') | |
323 | + end | |
324 | + | |
325 | + it 'year range 3' do | |
326 | + expect(desc('23 12 * JAN-MAR * 2013-2015')).to eq('À 12:23 PM, janvier à mars, 2013 à 2015') | |
327 | + end | |
328 | + | |
329 | + context 'multi part range seconds:' do | |
330 | + it 'multi part range seconds 2,4-5' do | |
331 | + expect(desc('2,4-5 1 * * *')).to eq("Minutes 02,04 à 05 après l'heure, à 1:00 AM") | |
332 | + end | |
333 | + | |
334 | + it 'multi part range seconds 2,26-28' do | |
335 | + expect(desc('2,26-28 18 * * *')).to eq("Minutes 02,26 à 28 après l'heure, à 6:00 PM") | |
336 | + end | |
337 | + end | |
338 | + | |
339 | + context 'minutes past the hour:' do | |
340 | + it 'minutes past the hour 5,10, midnight hour' do | |
341 | + expect(desc('5,10 0 * * *')).to eq("À 05 et 10 minutes après l'heure, à 12:00 AM") | |
342 | + end | |
343 | + | |
344 | + it 'minutes past the hour 5,10' do | |
345 | + expect(desc('5,10 * * * *')).to eq("À 05 et 10 minutes après l'heure") | |
346 | + end | |
347 | + | |
348 | + it 'minutes past the hour 5,10 day 2' do | |
349 | + expect(desc('5,10 * 2 * *')).to eq("À 05 et 10 minutes après l'heure, le 2 de chaque mois") | |
350 | + end | |
351 | + | |
352 | + it 'minutes past the hour 5/10 day 2' do | |
353 | + expect(desc('5/10 * 2 * *')).to eq("Tous les 10 minutes, commence à 05 minutes après l'heure, le 2 de chaque mois") | |
354 | + end | |
355 | + end | |
356 | + | |
357 | + context 'seconds past the minute:' do | |
358 | + it 'seconds past the minute 5,6, midnight hour' do | |
359 | + expect(desc('5,6 0 0 * * *')).to eq('À 5 et 6 secondes après la minute, à 12:00 AM') | |
360 | + end | |
361 | + | |
362 | + it 'seconds past the minute 5,6' do | |
363 | + expect(desc('5,6 0 * * * *')).to eq('À 5 et 6 secondes après la minute') | |
364 | + end | |
365 | + | |
366 | + it 'seconds past the minute 5,6 at 1' do | |
367 | + expect(desc('5,6 0 1 * * *')).to eq('À 5 et 6 secondes après la minute, à 1:00 AM') | |
368 | + end | |
369 | + | |
370 | + it 'seconds past the minute 5,6 day 2' do | |
371 | + expect(desc('5,6 0 * 2 * *')).to eq('À 5 et 6 secondes après la minute, le 2 de chaque mois') | |
372 | + end | |
373 | + end | |
374 | + | |
375 | + context 'increments starting at X > 1:' do | |
376 | + it 'second increments' do | |
377 | + expect(desc('5/15 0 * * * *')).to eq("Toutes les 15 secondes, commence à 5 secondes après la minute") | |
378 | + end | |
379 | + | |
380 | + it 'minute increments' do | |
381 | + expect(desc('30/10 * * * *')).to eq("Tous les 10 minutes, commence à 30 minutes après l'heure") | |
382 | + end | |
383 | + | |
384 | + it 'hour increments' do | |
385 | + expect(desc('0 30 2/6 * * ?')).to eq("À 30 minutes après l'heure, tous les 6 heures, commence à 2:00 AM") | |
386 | + end | |
387 | + | |
388 | + it 'day of month increments' do | |
389 | + expect(desc('0 30 8 2/7 * *')).to eq('À 8:30 AM, tous les 7 jours, commence le 2 de chaque mois') | |
390 | + end | |
391 | + | |
392 | + it 'day of week increments' do | |
393 | + expect(desc('0 30 11 * * 2/2')).to eq('À 11:30 AM, tous les 2 jours de la semaine, commence le mardi') | |
394 | + end | |
395 | + | |
396 | + it 'month increments' do | |
397 | + expect(desc('0 20 10 * 2/3 THU')).to eq('À 10:20 AM, seulement le jeudi, tous les 3 mois, commence en février') | |
398 | + end | |
399 | + | |
400 | + it 'year increments' do | |
401 | + expect(desc('0 0 0 1 MAR * 2010/5')).to eq('À 12:00 AM, le 1 de chaque mois, seulement en mars, tous les 5 ans, commence en 2010') | |
402 | + end | |
403 | + end | |
404 | + end | |
405 | +end | ... | ... |
1 | +++ a/spec/exp_descriptor_it_spec.rb | |
... | ... | @@ -0,0 +1,405 @@ |
1 | +# encoding: utf-8 | |
2 | +require 'cronex' | |
3 | + | |
4 | +module Cronex | |
5 | + describe ExpressionDescriptor do | |
6 | + | |
7 | + def desc(expression, opts = {}) | |
8 | + opts[:locale] = 'it' | |
9 | + Cronex::ExpressionDescriptor.new(expression, opts).description | |
10 | + end | |
11 | + | |
12 | + let(:opts) { { zero_based_dow: false } } | |
13 | + | |
14 | + it 'every second' do | |
15 | + expect(desc('* * * * * *')).to eq('Ogni secondo') | |
16 | + end | |
17 | + | |
18 | + it 'every 45 seconds' do | |
19 | + expect(desc('*/45 * * * * *')).to eq('Ogni 45 secondi') | |
20 | + end | |
21 | + | |
22 | + it 'minute span' do | |
23 | + expect(desc('0-10 11 * * *')).to eq('Ogni minuto tra le 11:00 AM e le 11:10 AM') | |
24 | + end | |
25 | + | |
26 | + context 'every minute' do | |
27 | + it 'every minute' do | |
28 | + expect(desc('* * * * *')).to eq('Ogni minuto') | |
29 | + end | |
30 | + | |
31 | + it 'every minute */1' do | |
32 | + expect(desc('*/1 * * * *')).to eq('Ogni minuto') | |
33 | + end | |
34 | + | |
35 | + it 'every minute 0 0/1' do | |
36 | + expect(desc('0 0/1 * * * ?')).to eq('Ogni minuto') | |
37 | + end | |
38 | + end | |
39 | + | |
40 | + context 'every X minutes:' do | |
41 | + it 'every 5 minuti' do | |
42 | + expect(desc('*/5 * * * *')).to eq('Ogni 5 minuti') | |
43 | + end | |
44 | + | |
45 | + it 'every 5 minutes at Midnight' do | |
46 | + expect(desc('*/5 0 * * *')).to eq('Ogni 5 minuti, alle(ai) 12:00 AM') | |
47 | + end | |
48 | + | |
49 | + it 'every 5 minutes 0 */5' do | |
50 | + expect(desc('0 */5 * * * *')).to eq('Ogni 5 minuti') | |
51 | + end | |
52 | + | |
53 | + it 'every 10 minutes 0 0/10' do | |
54 | + expect(desc('0 0/10 * * * ?')).to eq('Ogni 10 minuti') | |
55 | + end | |
56 | + end | |
57 | + | |
58 | + context 'every hour:' do | |
59 | + it 'every hour 0 0' do | |
60 | + expect(desc('0 0 * * * ?')).to eq('Ogni ora') | |
61 | + end | |
62 | + | |
63 | + it 'every hour 0 0 0/1' do | |
64 | + expect(desc('0 0 0/1 * * ?')).to eq('Ogni ora') | |
65 | + end | |
66 | + end | |
67 | + | |
68 | + context 'daily:' do | |
69 | + it 'daily at /\d\d/:/\d\d/' do | |
70 | + expect(desc('30 11 * * *')).to eq('Alle(ai) 11:30 AM') | |
71 | + end | |
72 | + | |
73 | + it 'daily at /\d/:/\d/' do | |
74 | + expect(desc('9 8 * * *')).to eq('Alle(ai) 8:09 AM') | |
75 | + end | |
76 | + | |
77 | + it 'daily at /0[89]/:/0[89]/' do | |
78 | + expect(desc('09 08 * * *')).to eq('Alle(ai) 8:09 AM') | |
79 | + end | |
80 | + | |
81 | + it 'daily at /0[1-7]/ /0[1-7/' do | |
82 | + expect(desc('02 01 * * *')).to eq('Alle(ai) 1:02 AM') | |
83 | + end | |
84 | + end | |
85 | + | |
86 | + context 'time of day certain days of week:' do | |
87 | + it 'time of day on MON-FRI' do | |
88 | + expect(desc('0 23 ? * MON-FRI')).to eq('Alle(ai) 11:00 PM, da lunedì a venerdì') | |
89 | + end | |
90 | + | |
91 | + it 'time of day on 1-5' do | |
92 | + expect(desc('30 11 * * 1-5')).to eq('Alle(ai) 11:30 AM, da lunedì a venerdì') | |
93 | + end | |
94 | + end | |
95 | + | |
96 | + it 'one month only' do | |
97 | + expect(desc('* * * 3 *')).to eq('Ogni minuto, solo a(nel) marzo') | |
98 | + end | |
99 | + | |
100 | + it 'two months only' do | |
101 | + expect(desc('* * * 3,6 *')).to eq('Ogni minuto, solo a(nel) marzo e giugno') | |
102 | + end | |
103 | + | |
104 | + it 'two times each afternoon' do | |
105 | + expect(desc('30 14,16 * * *')).to eq('Alle(ai) 2:30 PM e 4:30 PM') | |
106 | + end | |
107 | + | |
108 | + it 'three times daily' do | |
109 | + expect(desc('30 6,14,16 * * *')).to eq('Alle(ai) 6:30 AM, 2:30 PM e 4:30 PM') | |
110 | + end | |
111 | + | |
112 | + context 'once a week:' do | |
113 | + it 'once a week 0' do | |
114 | + expect(desc('46 9 * * 0')).to eq('Alle(ai) 9:46 AM, solo di domenica') | |
115 | + end | |
116 | + | |
117 | + it 'once a week SUN' do | |
118 | + expect(desc('46 9 * * SUN')).to eq('Alle(ai) 9:46 AM, solo di domenica') | |
119 | + end | |
120 | + | |
121 | + it 'once a week 7' do | |
122 | + expect(desc('46 9 * * 7')).to eq('Alle(ai) 9:46 AM, solo di domenica') | |
123 | + end | |
124 | + | |
125 | + it 'once a week 1' do | |
126 | + expect(desc('46 9 * * 1')).to eq('Alle(ai) 9:46 AM, solo di lunedì') | |
127 | + end | |
128 | + | |
129 | + it 'once a week 6' do | |
130 | + expect(desc('46 9 * * 6')).to eq('Alle(ai) 9:46 AM, solo di sabato') | |
131 | + end | |
132 | + end | |
133 | + | |
134 | + context 'once a week non zero based:' do | |
135 | + it 'once a week 1' do | |
136 | + expect(desc('46 9 * * 1', opts)).to eq('Alle(ai) 9:46 AM, solo di domenica') | |
137 | + end | |
138 | + | |
139 | + it 'once a week SUN' do | |
140 | + expect(desc('46 9 * * SUN', opts)).to eq('Alle(ai) 9:46 AM, solo di domenica') | |
141 | + end | |
142 | + | |
143 | + it 'once a week 2' do | |
144 | + expect(desc('46 9 * * 2', opts)).to eq('Alle(ai) 9:46 AM, solo di lunedì') | |
145 | + end | |
146 | + | |
147 | + it 'once a week 7' do | |
148 | + expect(desc('46 9 * * 7', opts)).to eq('Alle(ai) 9:46 AM, solo di sabato') | |
149 | + end | |
150 | + end | |
151 | + | |
152 | + context 'twice a week:' do | |
153 | + it 'twice a week 1,2' do | |
154 | + expect(desc('46 9 * * 1,2')).to eq('Alle(ai) 9:46 AM, solo di lunedì e martedì') | |
155 | + end | |
156 | + | |
157 | + it 'twice a week MON,TUE' do | |
158 | + expect(desc('46 9 * * MON,TUE')).to eq('Alle(ai) 9:46 AM, solo di lunedì e martedì') | |
159 | + end | |
160 | + | |
161 | + it 'twice a week 0,6' do | |
162 | + expect(desc('46 9 * * 0,6')).to eq('Alle(ai) 9:46 AM, solo di domenica e sabato') | |
163 | + end | |
164 | + | |
165 | + it 'twice a week 6,7' do | |
166 | + expect(desc('46 9 * * 6,7')).to eq('Alle(ai) 9:46 AM, solo di sabato e domenica') | |
167 | + end | |
168 | + end | |
169 | + | |
170 | + context 'twice a week non zero based:' do | |
171 | + it 'twice a week 1,2' do | |
172 | + expect(desc('46 9 * * 1,2', opts)).to eq('Alle(ai) 9:46 AM, solo di domenica e lunedì') | |
173 | + end | |
174 | + | |
175 | + it 'twice a week SUN,MON' do | |
176 | + expect(desc('46 9 * * SUN,MON', opts)).to eq('Alle(ai) 9:46 AM, solo di domenica e lunedì') | |
177 | + end | |
178 | + | |
179 | + it 'twice a week 6,7' do | |
180 | + expect(desc('46 9 * * 6,7', opts)).to eq('Alle(ai) 9:46 AM, solo di venerdì e sabato') | |
181 | + end | |
182 | + end | |
183 | + | |
184 | + it 'day of month' do | |
185 | + expect(desc('23 12 15 * *')).to eq('Alle(ai) 12:23 PM, il giorno 15 del mese') | |
186 | + end | |
187 | + | |
188 | + it 'day of month with day of week' do | |
189 | + expect(desc('23 12 15 * SUN')).to eq('Alle(ai) 12:23 PM, il giorno 15 del mese, solo di domenica') | |
190 | + end | |
191 | + | |
192 | + it 'month name' do | |
193 | + expect(desc('23 12 * JAN *')).to eq('Alle(ai) 12:23 PM, solo a(nel) gennaio') | |
194 | + end | |
195 | + | |
196 | + it 'day of month with question mark' do | |
197 | + expect(desc('23 12 ? JAN *')).to eq('Alle(ai) 12:23 PM, solo a(nel) gennaio') | |
198 | + end | |
199 | + | |
200 | + it 'month name range 2' do | |
201 | + expect(desc('23 12 * JAN-FEB *')).to eq('Alle(ai) 12:23 PM, da gennaio a febbraio') | |
202 | + end | |
203 | + | |
204 | + it 'month name range 3' do | |
205 | + expect(desc('23 12 * JAN-MAR *')).to eq('Alle(ai) 12:23 PM, da gennaio a marzo') | |
206 | + end | |
207 | + | |
208 | + it 'day of week name' do | |
209 | + expect(desc('23 12 * * SUN')).to eq('Alle(ai) 12:23 PM, solo di domenica') | |
210 | + end | |
211 | + | |
212 | + context 'day of week range:' do | |
213 | + it 'day of week range MON-FRI' do | |
214 | + expect(desc('*/5 15 * * MON-FRI')).to eq('Ogni 5 minuti, alle(ai) 3:00 PM, da lunedì a venerdì') | |
215 | + end | |
216 | + | |
217 | + it 'day of week range 0-6' do | |
218 | + expect(desc('*/5 15 * * 0-6')).to eq('Ogni 5 minuti, alle(ai) 3:00 PM, da domenica a sabato') | |
219 | + end | |
220 | + | |
221 | + it 'day of week range 6-7' do | |
222 | + expect(desc('*/5 15 * * 6-7')).to eq('Ogni 5 minuti, alle(ai) 3:00 PM, da sabato a domenica') | |
223 | + end | |
224 | + end | |
225 | + | |
226 | + context 'day of week once in month:' do | |
227 | + it 'day of week once MON#3' do | |
228 | + expect(desc('* * * * MON#3')).to eq('Ogni minuto, il(la) terzo(a) lunedì del mese') | |
229 | + end | |
230 | + | |
231 | + it 'day of week once 0#3' do | |
232 | + expect(desc('* * * * 0#3')).to eq('Ogni minuto, il(la) terzo(a) domenica del mese') | |
233 | + end | |
234 | + end | |
235 | + | |
236 | + context 'last day of week del mese:' do | |
237 | + it 'last day of week 4L' do | |
238 | + expect(desc('* * * * 4L')).to eq('Ogni minuto, l\'ultimo(a) giovedì del mese') | |
239 | + end | |
240 | + | |
241 | + it 'last day of week 0L' do | |
242 | + expect(desc('* * * * 0L')).to eq('Ogni minuto, l\'ultimo(a) domenica del mese') | |
243 | + end | |
244 | + end | |
245 | + | |
246 | + context 'last day of the month:' do | |
247 | + it 'on the last day of the month' do | |
248 | + expect(desc('*/5 * L JAN *')).to eq('Ogni 5 minuti, l\'ultimo giorno del mese, solo a(nel) gennaio') | |
249 | + end | |
250 | + | |
251 | + it 'between a day and last day of the month' do | |
252 | + expect(desc('*/5 * 23-L JAN *')).to eq('Ogni 5 minuti, tra il giorno 23 e il ultimo giorno del mese, solo a(nel) gennaio') | |
253 | + end | |
254 | + end | |
255 | + | |
256 | + it 'time of day with seconds' do | |
257 | + expect(desc('30 02 14 * * *')).to eq('Alle(ai) 2:02:30 PM') | |
258 | + end | |
259 | + | |
260 | + it 'second intervals' do | |
261 | + expect(desc('5-10 * * * * *')).to eq('Dal secondo 5 al 10 dopo il minuto') | |
262 | + end | |
263 | + | |
264 | + it 'second minutes hours intervals' do | |
265 | + expect(desc('5-10 30-35 10-12 * * *')).to eq( | |
266 | + 'Dal secondo 5 al 10 dopo il minuto, dal minuto 30 al 35 dopo l\'ora, tra le 10:00 AM e le 12:59 PM') | |
267 | + end | |
268 | + | |
269 | + it 'every 5 minutes at 30 seconds' do | |
270 | + expect(desc('30 */5 * * * *')).to eq('A 30 secondi dopo il minuto, ogni 5 minuti') | |
271 | + end | |
272 | + | |
273 | + it 'minutes past the hour range' do | |
274 | + expect(desc('0 30 10-13 ? * WED,FRI')).to eq( | |
275 | + 'Alle(ai) 30 minuti dopo l\'ora, tra le 10:00 AM e le 1:59 PM, solo di mercoledì e venerdì') | |
276 | + end | |
277 | + | |
278 | + it 'seconds past the minute interval' do | |
279 | + expect(desc('10 0/5 * * * ?')).to eq('A 10 secondi dopo il minuto, ogni 5 minuti') | |
280 | + end | |
281 | + | |
282 | + it 'between with interval' do | |
283 | + expect(desc('2-59/3 1,9,22 11-26 1-6 ?')).to eq( | |
284 | + 'Ogni 3 minuti, dal minuto 02 al 59 dopo l\'ora, alle(ai) 1:00 AM, 9:00 AM e 10:00 PM, tra il giorno 11 e il 26 del mese, da gennaio a giugno') | |
285 | + end | |
286 | + | |
287 | + it 'recurring first of month' do | |
288 | + expect(desc('0 0 6 1/1 * ?')).to eq('Alle(ai) 6:00 AM') | |
289 | + end | |
290 | + | |
291 | + it 'minutes past the hour' do | |
292 | + expect(desc('0 5 0/1 * * ?')).to eq('Alle(ai) 05 minuti dopo l\'ora') | |
293 | + end | |
294 | + | |
295 | + it 'every past the hour' do | |
296 | + expect(desc('0 0,5,10,15,20,25,30,35,40,45,50,55 * ? * *')).to eq( | |
297 | + 'Alle(ai) 00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50 e 55 minuti dopo l\'ora') | |
298 | + end | |
299 | + | |
300 | + it 'every X minutes past the hour with interval' do | |
301 | + expect(desc('0 0-30/2 17 ? * MON-FRI')).to eq( | |
302 | + 'Ogni 2 minuti, dal minuto 00 al 30 dopo l\'ora, alle(ai) 5:00 PM, da lunedì a venerdì') | |
303 | + end | |
304 | + | |
305 | + it 'every X days with interval' do | |
306 | + expect(desc('30 7 1-L/2 * *')).to eq('Alle(ai) 7:30 AM, ogni 2 giorni, tra il giorno 1 e il ultimo giorno del mese') | |
307 | + end | |
308 | + | |
309 | + it 'one year only with seconds' do | |
310 | + expect(desc('* * * * * * 2013')).to eq('Ogni secondo, solo a(nel) 2013') | |
311 | + end | |
312 | + | |
313 | + it 'one year only without seconds' do | |
314 | + expect(desc('* * * * * 2013')).to eq('Ogni minuto, solo a(nel) 2013') | |
315 | + end | |
316 | + | |
317 | + it 'two years only' do | |
318 | + expect(desc('* * * * * 2013,2014')).to eq('Ogni minuto, solo a(nel) 2013 e 2014') | |
319 | + end | |
320 | + | |
321 | + it 'year range 2' do | |
322 | + expect(desc('23 12 * JAN-FEB * 2013-2014')).to eq('Alle(ai) 12:23 PM, da gennaio a febbraio, da 2013 a 2014') | |
323 | + end | |
324 | + | |
325 | + it 'year range 3' do | |
326 | + expect(desc('23 12 * JAN-MAR * 2013-2015')).to eq('Alle(ai) 12:23 PM, da gennaio a marzo, da 2013 a 2015') | |
327 | + end | |
328 | + | |
329 | + context 'multi part range seconds:' do | |
330 | + it 'multi part range seconds 2,4-5' do | |
331 | + expect(desc('2,4-5 1 * * *')).to eq('Dal minuto 02,04 al 05 dopo l\'ora, alle(ai) 1:00 AM') | |
332 | + end | |
333 | + | |
334 | + it 'multi part range seconds 2,26-28' do | |
335 | + expect(desc('2,26-28 18 * * *')).to eq('Dal minuto 02,26 al 28 dopo l\'ora, alle(ai) 6:00 PM') | |
336 | + end | |
337 | + end | |
338 | + | |
339 | + context 'minutes past the hour:' do | |
340 | + it 'minutes past the hour 5,10, midnight hour' do | |
341 | + expect(desc('5,10 0 * * *')).to eq('Alle(ai) 05 e 10 minuti dopo l\'ora, alle(ai) 12:00 AM') | |
342 | + end | |
343 | + | |
344 | + it 'minutes past the hour 5,10' do | |
345 | + expect(desc('5,10 * * * *')).to eq('Alle(ai) 05 e 10 minuti dopo l\'ora') | |
346 | + end | |
347 | + | |
348 | + it 'minutes past the hour 5,10 day 2' do | |
349 | + expect(desc('5,10 * 2 * *')).to eq('Alle(ai) 05 e 10 minuti dopo l\'ora, il giorno 2 del mese') | |
350 | + end | |
351 | + | |
352 | + it 'minutes past the hour 5/10 day 2' do | |
353 | + expect(desc('5/10 * 2 * *')).to eq('Ogni 10 minuti, a partire da alle(ai) 05 minuti dopo l\'ora, il giorno 2 del mese') | |
354 | + end | |
355 | + end | |
356 | + | |
357 | + context 'seconds past the minute:' do | |
358 | + it 'seconds past the minute 5,6, midnight hour' do | |
359 | + expect(desc('5,6 0 0 * * *')).to eq('A 5 e 6 secondi dopo il minuto, alle(ai) 12:00 AM') | |
360 | + end | |
361 | + | |
362 | + it 'seconds past the minute 5,6' do | |
363 | + expect(desc('5,6 0 * * * *')).to eq('A 5 e 6 secondi dopo il minuto') | |
364 | + end | |
365 | + | |
366 | + it 'seconds past the minute 5,6 at 1' do | |
367 | + expect(desc('5,6 0 1 * * *')).to eq('A 5 e 6 secondi dopo il minuto, alle(ai) 1:00 AM') | |
368 | + end | |
369 | + | |
370 | + it 'seconds past the minute 5,6 day 2' do | |
371 | + expect(desc('5,6 0 * 2 * *')).to eq('A 5 e 6 secondi dopo il minuto, il giorno 2 del mese') | |
372 | + end | |
373 | + end | |
374 | + | |
375 | + context 'increments starting at X > 1:' do | |
376 | + it 'second increments' do | |
377 | + expect(desc('5/15 0 * * * *')).to eq('Ogni 15 secondi, a partire da a 5 secondi dopo il minuto') | |
378 | + end | |
379 | + | |
380 | + it 'minute increments' do | |
381 | + expect(desc('30/10 * * * *')).to eq('Ogni 10 minuti, a partire da alle(ai) 30 minuti dopo l\'ora') | |
382 | + end | |
383 | + | |
384 | + it 'hour increments' do | |
385 | + expect(desc('0 30 2/6 * * ?')).to eq('Alle(ai) 30 minuti dopo l\'ora, ogni 6 ore, a partire da alle(ai) 2:00 AM') | |
386 | + end | |
387 | + | |
388 | + it 'day of month increments' do | |
389 | + expect(desc('0 30 8 2/7 * *')).to eq('Alle(ai) 8:30 AM, ogni 7 giorni, a partire da il giorno 2 del mese') | |
390 | + end | |
391 | + | |
392 | + it 'day of week increments' do | |
393 | + expect(desc('0 30 11 * * 2/2')).to eq('Alle(ai) 11:30 AM, 2 giorni alla settimana, a partire da il martedì') | |
394 | + end | |
395 | + | |
396 | + it 'month increments' do | |
397 | + expect(desc('0 20 10 * 2/3 THU')).to eq('Alle(ai) 10:20 AM, solo di giovedì, ogni 3 mesi, a partire da febbraio') | |
398 | + end | |
399 | + | |
400 | + it 'year increments' do | |
401 | + expect(desc('0 0 0 1 MAR * 2010/5')).to eq('Alle(ai) 12:00 AM, il giorno 1 del mese, solo a(nel) marzo, ogni 5 anni, a partire da 2010') | |
402 | + end | |
403 | + end | |
404 | + end | |
405 | +end | ... | ... |
1 | +++ a/spec/exp_descriptor_pt_BR_spec.rb | |
... | ... | @@ -0,0 +1,405 @@ |
1 | +# encoding: utf-8 | |
2 | +require 'cronex' | |
3 | + | |
4 | +module Cronex | |
5 | + describe ExpressionDescriptor do | |
6 | + | |
7 | + def desc(expression, opts = {}) | |
8 | + opts[:locale] = 'pt_BR' | |
9 | + Cronex::ExpressionDescriptor.new(expression, opts).description | |
10 | + end | |
11 | + | |
12 | + let(:opts) { { zero_based_dow: false } } | |
13 | + | |
14 | + it 'every second' do | |
15 | + expect(desc('* * * * * *')).to eq('A cada segundo') | |
16 | + end | |
17 | + | |
18 | + it 'every 45 seconds' do | |
19 | + expect(desc('*/45 * * * * *')).to eq('A cada 45 segundos') | |
20 | + end | |
21 | + | |
22 | + it 'minute span' do | |
23 | + expect(desc('0-10 11 * * *')).to eq('A cada minuto entre 11:00 AM e 11:10 AM') | |
24 | + end | |
25 | + | |
26 | + context 'every minute' do | |
27 | + it 'every minute' do | |
28 | + expect(desc('* * * * *')).to eq('A cada minuto') | |
29 | + end | |
30 | + | |
31 | + it 'every minute */1' do | |
32 | + expect(desc('*/1 * * * *')).to eq('A cada minuto') | |
33 | + end | |
34 | + | |
35 | + it 'every minute 0 0/1' do | |
36 | + expect(desc('0 0/1 * * * ?')).to eq('A cada minuto') | |
37 | + end | |
38 | + end | |
39 | + | |
40 | + context 'every X minutes:' do | |
41 | + it 'every 5 minutes' do | |
42 | + expect(desc('*/5 * * * *')).to eq('A cada 5 minutos') | |
43 | + end | |
44 | + | |
45 | + it 'every 5 minutes at Midnight' do | |
46 | + expect(desc('*/5 0 * * *')).to eq('A cada 5 minutos, 12:00 AM') | |
47 | + end | |
48 | + | |
49 | + it 'every 5 minutes 0 */5' do | |
50 | + expect(desc('0 */5 * * * *')).to eq('A cada 5 minutos') | |
51 | + end | |
52 | + | |
53 | + it 'every 10 minutes 0 0/10' do | |
54 | + expect(desc('0 0/10 * * * ?')).to eq('A cada 10 minutos') | |
55 | + end | |
56 | + end | |
57 | + | |
58 | + context 'every hour:' do | |
59 | + it 'every hour 0 0' do | |
60 | + expect(desc('0 0 * * * ?')).to eq('A cada hora') | |
61 | + end | |
62 | + | |
63 | + it 'every hour 0 0 0/1' do | |
64 | + expect(desc('0 0 0/1 * * ?')).to eq('A cada hora') | |
65 | + end | |
66 | + end | |
67 | + | |
68 | + context 'daily:' do | |
69 | + it 'daily at /\d\d/:/\d\d/' do | |
70 | + expect(desc('30 11 * * *')).to eq('Às 11:30 AM') | |
71 | + end | |
72 | + | |
73 | + it 'daily at /\d/:/\d/' do | |
74 | + expect(desc('9 8 * * *')).to eq('Às 8:09 AM') | |
75 | + end | |
76 | + | |
77 | + it 'daily at /0[89]/:/0[89]/' do | |
78 | + expect(desc('09 08 * * *')).to eq('Às 8:09 AM') | |
79 | + end | |
80 | + | |
81 | + it 'daily at /0[1-7]/ /0[1-7/' do | |
82 | + expect(desc('02 01 * * *')).to eq('Às 1:02 AM') | |
83 | + end | |
84 | + end | |
85 | + | |
86 | + context 'time of day certain days of week:' do | |
87 | + it 'time of day on MON-FRI' do | |
88 | + expect(desc('0 23 ? * MON-FRI')).to eq('Às 11:00 PM, de segunda-feira a sexta-feira') | |
89 | + end | |
90 | + | |
91 | + it 'time of day on 1-5' do | |
92 | + expect(desc('30 11 * * 1-5')).to eq('Às 11:30 AM, de segunda-feira a sexta-feira') | |
93 | + end | |
94 | + end | |
95 | + | |
96 | + it 'one month todo(a)' do | |
97 | + expect(desc('* * * 3 *')).to eq('A cada minuto, em março') | |
98 | + end | |
99 | + | |
100 | + it 'two months todo(a)' do | |
101 | + expect(desc('* * * 3,6 *')).to eq('A cada minuto, em março e junho') | |
102 | + end | |
103 | + | |
104 | + it 'two times each afternoon' do | |
105 | + expect(desc('30 14,16 * * *')).to eq('Às 2:30 PM e 4:30 PM') | |
106 | + end | |
107 | + | |
108 | + it 'three times daily' do | |
109 | + expect(desc('30 6,14,16 * * *')).to eq('Às 6:30 AM, 2:30 PM e 4:30 PM') | |
110 | + end | |
111 | + | |
112 | + context 'once a week:' do | |
113 | + it 'once a week 0' do | |
114 | + expect(desc('46 9 * * 0')).to eq('Às 9:46 AM, todo(a) domingo') | |
115 | + end | |
116 | + | |
117 | + it 'once a week SUN' do | |
118 | + expect(desc('46 9 * * SUN')).to eq('Às 9:46 AM, todo(a) domingo') | |
119 | + end | |
120 | + | |
121 | + it 'once a week 7' do | |
122 | + expect(desc('46 9 * * 7')).to eq('Às 9:46 AM, todo(a) domingo') | |
123 | + end | |
124 | + | |
125 | + it 'once a week 1' do | |
126 | + expect(desc('46 9 * * 1')).to eq('Às 9:46 AM, todo(a) segunda-feira') | |
127 | + end | |
128 | + | |
129 | + it 'once a week 6' do | |
130 | + expect(desc('46 9 * * 6')).to eq('Às 9:46 AM, todo(a) sábado') | |
131 | + end | |
132 | + end | |
133 | + | |
134 | + context 'once a week non zero based:' do | |
135 | + it 'once a week 1' do | |
136 | + expect(desc('46 9 * * 1', opts)).to eq('Às 9:46 AM, todo(a) domingo') | |
137 | + end | |
138 | + | |
139 | + it 'once a week SUN' do | |
140 | + expect(desc('46 9 * * SUN', opts)).to eq('Às 9:46 AM, todo(a) domingo') | |
141 | + end | |
142 | + | |
143 | + it 'once a week 2' do | |
144 | + expect(desc('46 9 * * 2', opts)).to eq('Às 9:46 AM, todo(a) segunda-feira') | |
145 | + end | |
146 | + | |
147 | + it 'once a week 7' do | |
148 | + expect(desc('46 9 * * 7', opts)).to eq('Às 9:46 AM, todo(a) sábado') | |
149 | + end | |
150 | + end | |
151 | + | |
152 | + context 'twice a week:' do | |
153 | + it 'twice a week 1,2' do | |
154 | + expect(desc('46 9 * * 1,2')).to eq('Às 9:46 AM, todo(a) segunda-feira e terça-feira') | |
155 | + end | |
156 | + | |
157 | + it 'twice a week MON,TUE' do | |
158 | + expect(desc('46 9 * * MON,TUE')).to eq('Às 9:46 AM, todo(a) segunda-feira e terça-feira') | |
159 | + end | |
160 | + | |
161 | + it 'twice a week 0,6' do | |
162 | + expect(desc('46 9 * * 0,6')).to eq('Às 9:46 AM, todo(a) domingo e sábado') | |
163 | + end | |
164 | + | |
165 | + it 'twice a week 6,7' do | |
166 | + expect(desc('46 9 * * 6,7')).to eq('Às 9:46 AM, todo(a) sábado e domingo') | |
167 | + end | |
168 | + end | |
169 | + | |
170 | + context 'twice a week non zero based:' do | |
171 | + it 'twice a week 1,2' do | |
172 | + expect(desc('46 9 * * 1,2', opts)).to eq('Às 9:46 AM, todo(a) domingo e segunda-feira') | |
173 | + end | |
174 | + | |
175 | + it 'twice a week SUN,MON' do | |
176 | + expect(desc('46 9 * * SUN,MON', opts)).to eq('Às 9:46 AM, todo(a) domingo e segunda-feira') | |
177 | + end | |
178 | + | |
179 | + it 'twice a week 6,7' do | |
180 | + expect(desc('46 9 * * 6,7', opts)).to eq('Às 9:46 AM, todo(a) sexta-feira e sábado') | |
181 | + end | |
182 | + end | |
183 | + | |
184 | + it 'day of month' do | |
185 | + expect(desc('23 12 15 * *')).to eq('Às 12:23 PM, no dia 15 do mês') | |
186 | + end | |
187 | + | |
188 | + it 'day of month with day of week' do | |
189 | + expect(desc('23 12 15 * SUN')).to eq('Às 12:23 PM, no dia 15 do mês, todo(a) domingo') | |
190 | + end | |
191 | + | |
192 | + it 'month name' do | |
193 | + expect(desc('23 12 * JAN *')).to eq('Às 12:23 PM, em janeiro') | |
194 | + end | |
195 | + | |
196 | + it 'day of month with question mark' do | |
197 | + expect(desc('23 12 ? JAN *')).to eq('Às 12:23 PM, em janeiro') | |
198 | + end | |
199 | + | |
200 | + it 'month name range 2' do | |
201 | + expect(desc('23 12 * JAN-FEB *')).to eq('Às 12:23 PM, de janeiro a fevereiro') | |
202 | + end | |
203 | + | |
204 | + it 'month name range 3' do | |
205 | + expect(desc('23 12 * JAN-MAR *')).to eq('Às 12:23 PM, de janeiro a março') | |
206 | + end | |
207 | + | |
208 | + it 'day of week name' do | |
209 | + expect(desc('23 12 * * SUN')).to eq('Às 12:23 PM, todo(a) domingo') | |
210 | + end | |
211 | + | |
212 | + context 'day of week range:' do | |
213 | + it 'day of week range MON-FRI' do | |
214 | + expect(desc('*/5 15 * * MON-FRI')).to eq('A cada 5 minutos, 3:00 PM, de segunda-feira a sexta-feira') | |
215 | + end | |
216 | + | |
217 | + it 'day of week range 0-6' do | |
218 | + expect(desc('*/5 15 * * 0-6')).to eq('A cada 5 minutos, 3:00 PM, de domingo a sábado') | |
219 | + end | |
220 | + | |
221 | + it 'day of week range 6-7' do | |
222 | + expect(desc('*/5 15 * * 6-7')).to eq('A cada 5 minutos, 3:00 PM, de sábado a domingo') | |
223 | + end | |
224 | + end | |
225 | + | |
226 | + context 'day of week once in month:' do | |
227 | + it 'day of week once MON#3' do | |
228 | + expect(desc('* * * * MON#3')).to eq('A cada minuto, no(a) terceiro(a) segunda-feira do mês') | |
229 | + end | |
230 | + | |
231 | + it 'day of week once 0#3' do | |
232 | + expect(desc('* * * * 0#3')).to eq('A cada minuto, no(a) terceiro(a) domingo do mês') | |
233 | + end | |
234 | + end | |
235 | + | |
236 | + context 'last day of week of the month:' do | |
237 | + it 'last day of week 4L' do | |
238 | + expect(desc('* * * * 4L')).to eq('A cada minuto, no(a) último(a) quinta-feira do mês') | |
239 | + end | |
240 | + | |
241 | + it 'last day of week 0L' do | |
242 | + expect(desc('* * * * 0L')).to eq('A cada minuto, no(a) último(a) domingo do mês') | |
243 | + end | |
244 | + end | |
245 | + | |
246 | + context 'last day of the month:' do | |
247 | + it 'on the last day of the month' do | |
248 | + expect(desc('*/5 * L JAN *')).to eq('A cada 5 minutos, no último dia do mês, em janeiro') | |
249 | + end | |
250 | + | |
251 | + it 'between a day and last day of the month' do | |
252 | + expect(desc('*/5 * 23-L JAN *')).to eq('A cada 5 minutos, entre os dias 23 e último dia do mês, em janeiro') | |
253 | + end | |
254 | + end | |
255 | + | |
256 | + it 'time of day with seconds' do | |
257 | + expect(desc('30 02 14 * * *')).to eq('Às 2:02:30 PM') | |
258 | + end | |
259 | + | |
260 | + it 'second intervals' do | |
261 | + expect(desc('5-10 * * * * *')).to eq('Entre 5 e 10 segundos após o minuto') | |
262 | + end | |
263 | + | |
264 | + it 'second minutes hours intervals' do | |
265 | + expect(desc('5-10 30-35 10-12 * * *')).to eq( | |
266 | + 'Entre 5 e 10 segundos após o minuto, entre 30 e 35 minutos após a hora, entre 10:00 AM e 12:59 PM') | |
267 | + end | |
268 | + | |
269 | + it 'every 5 minutes at 30 seconds' do | |
270 | + expect(desc('30 */5 * * * *')).to eq('30 segundos após o minuto, a cada 5 minutos') | |
271 | + end | |
272 | + | |
273 | + it 'minutes past the hour range' do | |
274 | + expect(desc('0 30 10-13 ? * WED,FRI')).to eq( | |
275 | + '30 minutos após a hora, entre 10:00 AM e 1:59 PM, todo(a) quarta-feira e sexta-feira') | |
276 | + end | |
277 | + | |
278 | + it 'seconds past the minute interval' do | |
279 | + expect(desc('10 0/5 * * * ?')).to eq('10 segundos após o minuto, a cada 5 minutos') | |
280 | + end | |
281 | + | |
282 | + it 'between with interval' do | |
283 | + expect(desc('2-59/3 1,9,22 11-26 1-6 ?')).to eq( | |
284 | + 'A cada 3 minutos, entre 02 e 59 minutos após a hora, 1:00 AM, 9:00 AM e 10:00 PM, entre os dias 11 e 26 do mês, de janeiro a junho') | |
285 | + end | |
286 | + | |
287 | + it 'recurring first of month' do | |
288 | + expect(desc('0 0 6 1/1 * ?')).to eq('Às 6:00 AM') | |
289 | + end | |
290 | + | |
291 | + it 'minutes past the hour' do | |
292 | + expect(desc('0 5 0/1 * * ?')).to eq('05 minutos após a hora') | |
293 | + end | |
294 | + | |
295 | + it 'every past the hour' do | |
296 | + expect(desc('0 0,5,10,15,20,25,30,35,40,45,50,55 * ? * *')).to eq( | |
297 | + '00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50 e 55 minutos após a hora') | |
298 | + end | |
299 | + | |
300 | + it 'every X minutes past the hour with interval' do | |
301 | + expect(desc('0 0-30/2 17 ? * MON-FRI')).to eq( | |
302 | + 'A cada 2 minutos, entre 00 e 30 minutos após a hora, 5:00 PM, de segunda-feira a sexta-feira') | |
303 | + end | |
304 | + | |
305 | + it 'every X days with interval' do | |
306 | + expect(desc('30 7 1-L/2 * *')).to eq('Às 7:30 AM, a cada 2 dias, entre os dias 1 e último dia do mês') | |
307 | + end | |
308 | + | |
309 | + it 'one year only with seconds' do | |
310 | + expect(desc('* * * * * * 2013')).to eq('A cada segundo, em 2013') | |
311 | + end | |
312 | + | |
313 | + it 'one year todo(a) without seconds' do | |
314 | + expect(desc('* * * * * 2013')).to eq('A cada minuto, em 2013') | |
315 | + end | |
316 | + | |
317 | + it 'two years todo(a)' do | |
318 | + expect(desc('* * * * * 2013,2014')).to eq('A cada minuto, em 2013 e 2014') | |
319 | + end | |
320 | + | |
321 | + it 'year range 2' do | |
322 | + expect(desc('23 12 * JAN-FEB * 2013-2014')).to eq('Às 12:23 PM, de janeiro a fevereiro, de 2013 a 2014') | |
323 | + end | |
324 | + | |
325 | + it 'year range 3' do | |
326 | + expect(desc('23 12 * JAN-MAR * 2013-2015')).to eq('Às 12:23 PM, de janeiro a março, de 2013 a 2015') | |
327 | + end | |
328 | + | |
329 | + context 'multi part range seconds:' do | |
330 | + it 'multi part range seconds 2,4-5' do | |
331 | + expect(desc('2,4-5 1 * * *')).to eq('Entre 02,04 e 05 minutos após a hora, 1:00 AM') | |
332 | + end | |
333 | + | |
334 | + it 'multi part range seconds 2,26-28' do | |
335 | + expect(desc('2,26-28 18 * * *')).to eq('Entre 02,26 e 28 minutos após a hora, 6:00 PM') | |
336 | + end | |
337 | + end | |
338 | + | |
339 | + context 'minutes past the hour:' do | |
340 | + it 'minutes past the hour 5,10, midnight hour' do | |
341 | + expect(desc('5,10 0 * * *')).to eq('05 e 10 minutos após a hora, 12:00 AM') | |
342 | + end | |
343 | + | |
344 | + it 'minutes past the hour 5,10' do | |
345 | + expect(desc('5,10 * * * *')).to eq('05 e 10 minutos após a hora') | |
346 | + end | |
347 | + | |
348 | + it 'minutes past the hour 5,10 day 2' do | |
349 | + expect(desc('5,10 * 2 * *')).to eq('05 e 10 minutos após a hora, no dia 2 do mês') | |
350 | + end | |
351 | + | |
352 | + it 'minutes past the hour 5/10 day 2' do | |
353 | + expect(desc('5/10 * 2 * *')).to eq('A cada 10 minutos, iniciando 05 minutos após a hora, no dia 2 do mês') | |
354 | + end | |
355 | + end | |
356 | + | |
357 | + context 'seconds past the minute:' do | |
358 | + it 'seconds past the minute 5,6, midnight hour' do | |
359 | + expect(desc('5,6 0 0 * * *')).to eq('5 e 6 segundos após o minuto, 12:00 AM') | |
360 | + end | |
361 | + | |
362 | + it 'seconds past the minute 5,6' do | |
363 | + expect(desc('5,6 0 * * * *')).to eq('5 e 6 segundos após o minuto') | |
364 | + end | |
365 | + | |
366 | + it 'seconds past the minute 5,6 at 1' do | |
367 | + expect(desc('5,6 0 1 * * *')).to eq('5 e 6 segundos após o minuto, 1:00 AM') | |
368 | + end | |
369 | + | |
370 | + it 'seconds past the minute 5,6 day 2' do | |
371 | + expect(desc('5,6 0 * 2 * *')).to eq('5 e 6 segundos após o minuto, no dia 2 do mês') | |
372 | + end | |
373 | + end | |
374 | + | |
375 | + context 'increments starting at X > 1:' do | |
376 | + it 'second increments' do | |
377 | + expect(desc('5/15 0 * * * *')).to eq('A cada 15 segundos, iniciando 5 segundos após o minuto') | |
378 | + end | |
379 | + | |
380 | + it 'minute increments' do | |
381 | + expect(desc('30/10 * * * *')).to eq('A cada 10 minutos, iniciando 30 minutos após a hora') | |
382 | + end | |
383 | + | |
384 | + it 'hour increments' do | |
385 | + expect(desc('0 30 2/6 * * ?')).to eq('30 minutos após a hora, a cada 6 horas, iniciando 2:00 AM') | |
386 | + end | |
387 | + | |
388 | + it 'day of month increments' do | |
389 | + expect(desc('0 30 8 2/7 * *')).to eq('Às 8:30 AM, a cada 7 dias, iniciando no dia 2 do mês') | |
390 | + end | |
391 | + | |
392 | + it 'day of week increments' do | |
393 | + expect(desc('0 30 11 * * 2/2')).to eq('Às 11:30 AM, a cada 2 dias da semana, iniciando terça-feira') | |
394 | + end | |
395 | + | |
396 | + it 'month increments' do | |
397 | + expect(desc('0 20 10 * 2/3 THU')).to eq('Às 10:20 AM, todo(a) quinta-feira, a cada 3 mêses, iniciando em fevereiro') | |
398 | + end | |
399 | + | |
400 | + it 'year increments' do | |
401 | + expect(desc('0 0 0 1 MAR * 2010/5')).to eq('Às 12:00 AM, no dia 1 do mês, em março, a cada 5 anos, iniciando em 2010') | |
402 | + end | |
403 | + end | |
404 | + end | |
405 | +end | ... | ... |
1 | +++ a/spec/exp_descriptor_ro_spec.rb | |
... | ... | @@ -0,0 +1,405 @@ |
1 | +# encoding: utf-8 | |
2 | +require 'cronex' | |
3 | + | |
4 | +module Cronex | |
5 | + describe ExpressionDescriptor do | |
6 | + | |
7 | + def desc(expression, opts = {}) | |
8 | + opts[:locale] = 'ro' | |
9 | + Cronex::ExpressionDescriptor.new(expression, opts).description | |
10 | + end | |
11 | + | |
12 | + let(:opts) { { zero_based_dow: false } } | |
13 | + | |
14 | + it 'every second' do | |
15 | + expect(desc('* * * * * *')).to eq('În fiecare secundă') | |
16 | + end | |
17 | + | |
18 | + it 'every 45 seconds' do | |
19 | + expect(desc('*/45 * * * * *')).to eq('La fiecare 45 secunde') | |
20 | + end | |
21 | + | |
22 | + it 'minute span' do | |
23 | + expect(desc('0-10 11 * * *')).to eq('În fiecare minut între 11:00 AM și 11:10 AM') | |
24 | + end | |
25 | + | |
26 | + context 'every minute' do | |
27 | + it 'every minute' do | |
28 | + expect(desc('* * * * *')).to eq('În fiecare minut') | |
29 | + end | |
30 | + | |
31 | + it 'every minute */1' do | |
32 | + expect(desc('*/1 * * * *')).to eq('În fiecare minut') | |
33 | + end | |
34 | + | |
35 | + it 'every minute 0 0/1' do | |
36 | + expect(desc('0 0/1 * * * ?')).to eq('În fiecare minut') | |
37 | + end | |
38 | + end | |
39 | + | |
40 | + context 'every X minutes:' do | |
41 | + it 'every 5 minutes' do | |
42 | + expect(desc('*/5 * * * *')).to eq('La fiecare 5 minute') | |
43 | + end | |
44 | + | |
45 | + it 'every 5 minutes at Midnight' do | |
46 | + expect(desc('*/5 0 * * *')).to eq('La fiecare 5 minute, la 12:00 AM') | |
47 | + end | |
48 | + | |
49 | + it 'every 5 minutes 0 */5' do | |
50 | + expect(desc('0 */5 * * * *')).to eq('La fiecare 5 minute') | |
51 | + end | |
52 | + | |
53 | + it 'every 10 minutes 0 0/10' do | |
54 | + expect(desc('0 0/10 * * * ?')).to eq('La fiecare 10 minute') | |
55 | + end | |
56 | + end | |
57 | + | |
58 | + context 'every hour:' do | |
59 | + it 'every hour 0 0' do | |
60 | + expect(desc('0 0 * * * ?')).to eq('În fiecare oră') | |
61 | + end | |
62 | + | |
63 | + it 'every hour 0 0 0/1' do | |
64 | + expect(desc('0 0 0/1 * * ?')).to eq('În fiecare oră') | |
65 | + end | |
66 | + end | |
67 | + | |
68 | + context 'daily:' do | |
69 | + it 'daily at /\d\d/:/\d\d/' do | |
70 | + expect(desc('30 11 * * *')).to eq('La 11:30 AM') | |
71 | + end | |
72 | + | |
73 | + it 'daily at /\d/:/\d/' do | |
74 | + expect(desc('9 8 * * *')).to eq('La 8:09 AM') | |
75 | + end | |
76 | + | |
77 | + it 'daily at /0[89]/:/0[89]/' do | |
78 | + expect(desc('09 08 * * *')).to eq('La 8:09 AM') | |
79 | + end | |
80 | + | |
81 | + it 'daily at /0[1-7]/ /0[1-7/' do | |
82 | + expect(desc('02 01 * * *')).to eq('La 1:02 AM') | |
83 | + end | |
84 | + end | |
85 | + | |
86 | + context 'time of day certain days of week:' do | |
87 | + it 'time of day on MON-FRI' do | |
88 | + expect(desc('0 23 ? * MON-FRI')).to eq('La 11:00 PM, de luni până vineri') | |
89 | + end | |
90 | + | |
91 | + it 'time of day on 1-5' do | |
92 | + expect(desc('30 11 * * 1-5')).to eq('La 11:30 AM, de luni până vineri') | |
93 | + end | |
94 | + end | |
95 | + | |
96 | + it 'one month only' do | |
97 | + expect(desc('* * * 3 *')).to eq('În fiecare minut, numai în martie') | |
98 | + end | |
99 | + | |
100 | + it 'two months only' do | |
101 | + expect(desc('* * * 3,6 *')).to eq('În fiecare minut, numai în martie și iunie') | |
102 | + end | |
103 | + | |
104 | + it 'two times each afternoon' do | |
105 | + expect(desc('30 14,16 * * *')).to eq('La 2:30 PM și 4:30 PM') | |
106 | + end | |
107 | + | |
108 | + it 'three times daily' do | |
109 | + expect(desc('30 6,14,16 * * *')).to eq('La 6:30 AM, 2:30 PM și 4:30 PM') | |
110 | + end | |
111 | + | |
112 | + context 'once a week:' do | |
113 | + it 'once a week 0' do | |
114 | + expect(desc('46 9 * * 0')).to eq('La 9:46 AM, numai duminică') | |
115 | + end | |
116 | + | |
117 | + it 'once a week SUN' do | |
118 | + expect(desc('46 9 * * SUN')).to eq('La 9:46 AM, numai duminică') | |
119 | + end | |
120 | + | |
121 | + it 'once a week 7' do | |
122 | + expect(desc('46 9 * * 7')).to eq('La 9:46 AM, numai duminică') | |
123 | + end | |
124 | + | |
125 | + it 'once a week 1' do | |
126 | + expect(desc('46 9 * * 1')).to eq('La 9:46 AM, numai luni') | |
127 | + end | |
128 | + | |
129 | + it 'once a week 6' do | |
130 | + expect(desc('46 9 * * 6')).to eq('La 9:46 AM, numai sâmbătă') | |
131 | + end | |
132 | + end | |
133 | + | |
134 | + context 'once a week non zero based:' do | |
135 | + it 'once a week 1' do | |
136 | + expect(desc('46 9 * * 1', opts)).to eq('La 9:46 AM, numai duminică') | |
137 | + end | |
138 | + | |
139 | + it 'once a week SUN' do | |
140 | + expect(desc('46 9 * * SUN', opts)).to eq('La 9:46 AM, numai duminică') | |
141 | + end | |
142 | + | |
143 | + it 'once a week 2' do | |
144 | + expect(desc('46 9 * * 2', opts)).to eq('La 9:46 AM, numai luni') | |
145 | + end | |
146 | + | |
147 | + it 'once a week 7' do | |
148 | + expect(desc('46 9 * * 7', opts)).to eq('La 9:46 AM, numai sâmbătă') | |
149 | + end | |
150 | + end | |
151 | + | |
152 | + context 'twice a week:' do | |
153 | + it 'twice a week 1,2' do | |
154 | + expect(desc('46 9 * * 1,2')).to eq('La 9:46 AM, numai luni și marți') | |
155 | + end | |
156 | + | |
157 | + it 'twice a week MON,TUE' do | |
158 | + expect(desc('46 9 * * MON,TUE')).to eq('La 9:46 AM, numai luni și marți') | |
159 | + end | |
160 | + | |
161 | + it 'twice a week 0,6' do | |
162 | + expect(desc('46 9 * * 0,6')).to eq('La 9:46 AM, numai duminică și sâmbătă') | |
163 | + end | |
164 | + | |
165 | + it 'twice a week 6,7' do | |
166 | + expect(desc('46 9 * * 6,7')).to eq('La 9:46 AM, numai sâmbătă și duminică') | |
167 | + end | |
168 | + end | |
169 | + | |
170 | + context 'twice a week non zero based:' do | |
171 | + it 'twice a week 1,2' do | |
172 | + expect(desc('46 9 * * 1,2', opts)).to eq('La 9:46 AM, numai duminică și luni') | |
173 | + end | |
174 | + | |
175 | + it 'twice a week SUN,MON' do | |
176 | + expect(desc('46 9 * * SUN,MON', opts)).to eq('La 9:46 AM, numai duminică și luni') | |
177 | + end | |
178 | + | |
179 | + it 'twice a week 6,7' do | |
180 | + expect(desc('46 9 * * 6,7', opts)).to eq('La 9:46 AM, numai vineri și sâmbătă') | |
181 | + end | |
182 | + end | |
183 | + | |
184 | + it 'day of month' do | |
185 | + expect(desc('23 12 15 * *')).to eq('La 12:23 PM, în a 15-a zi a lunii') | |
186 | + end | |
187 | + | |
188 | + it 'day of month with day of week' do | |
189 | + expect(desc('23 12 15 * SUN')).to eq('La 12:23 PM, în a 15-a zi a lunii, numai duminică') | |
190 | + end | |
191 | + | |
192 | + it 'month name' do | |
193 | + expect(desc('23 12 * JAN *')).to eq('La 12:23 PM, numai în ianuarie') | |
194 | + end | |
195 | + | |
196 | + it 'day of month with question mark' do | |
197 | + expect(desc('23 12 ? JAN *')).to eq('La 12:23 PM, numai în ianuarie') | |
198 | + end | |
199 | + | |
200 | + it 'month name range 2' do | |
201 | + expect(desc('23 12 * JAN-FEB *')).to eq('La 12:23 PM, din ianuarie până în februarie') | |
202 | + end | |
203 | + | |
204 | + it 'month name range 3' do | |
205 | + expect(desc('23 12 * JAN-MAR *')).to eq('La 12:23 PM, din ianuarie până în martie') | |
206 | + end | |
207 | + | |
208 | + it 'day of week name' do | |
209 | + expect(desc('23 12 * * SUN')).to eq('La 12:23 PM, numai duminică') | |
210 | + end | |
211 | + | |
212 | + context 'day of week range:' do | |
213 | + it 'day of week range MON-FRI' do | |
214 | + expect(desc('*/5 15 * * MON-FRI')).to eq('La fiecare 5 minute, la 3:00 PM, de luni până vineri') | |
215 | + end | |
216 | + | |
217 | + it 'day of week range 0-6' do | |
218 | + expect(desc('*/5 15 * * 0-6')).to eq('La fiecare 5 minute, la 3:00 PM, de duminică până sâmbătă') | |
219 | + end | |
220 | + | |
221 | + it 'day of week range 6-7' do | |
222 | + expect(desc('*/5 15 * * 6-7')).to eq('La fiecare 5 minute, la 3:00 PM, de sâmbătă până duminică') | |
223 | + end | |
224 | + end | |
225 | + | |
226 | + context 'day of week once in month:' do | |
227 | + it 'day of week once MON#3' do | |
228 | + expect(desc('* * * * MON#3')).to eq('În fiecare minut, în a treia luni a lunii') | |
229 | + end | |
230 | + | |
231 | + it 'day of week once 0#3' do | |
232 | + expect(desc('* * * * 0#3')).to eq('În fiecare minut, în a treia duminică a lunii') | |
233 | + end | |
234 | + end | |
235 | + | |
236 | + context 'last day of week of the month:' do | |
237 | + it 'last day of week 4L' do | |
238 | + expect(desc('* * * * 4L')).to eq('În fiecare minut, în ultima joi din lună') | |
239 | + end | |
240 | + | |
241 | + it 'last day of week 0L' do | |
242 | + expect(desc('* * * * 0L')).to eq('În fiecare minut, în ultima duminică din lună') | |
243 | + end | |
244 | + end | |
245 | + | |
246 | + context 'last day of the month:' do | |
247 | + it 'on the last day of the month' do | |
248 | + expect(desc('*/5 * L JAN *')).to eq('La fiecare 5 minute, în ultima zi a lunii, numai în ianuarie') | |
249 | + end | |
250 | + | |
251 | + it 'between a day and last day of the month' do | |
252 | + expect(desc('*/5 * 23-L JAN *')).to eq('La fiecare 5 minute, între zilele 23 și ultima zi a lunii, numai în ianuarie') | |
253 | + end | |
254 | + end | |
255 | + | |
256 | + it 'time of day with seconds' do | |
257 | + expect(desc('30 02 14 * * *')).to eq('La 2:02:30 PM') | |
258 | + end | |
259 | + | |
260 | + it 'second intervals' do | |
261 | + expect(desc('5-10 * * * * *')).to eq('Între secundele 5 și 10') | |
262 | + end | |
263 | + | |
264 | + it 'second minutes hours intervals' do | |
265 | + expect(desc('5-10 30-35 10-12 * * *')).to eq( | |
266 | + 'Între secundele 5 și 10, între minutele 30 și 35, între 10:00 AM și 12:59 PM') | |
267 | + end | |
268 | + | |
269 | + it 'every 5 minutes at 30 seconds' do | |
270 | + expect(desc('30 */5 * * * *')).to eq('La secunda 30, la fiecare 5 minute') | |
271 | + end | |
272 | + | |
273 | + it 'minutes past the hour range' do | |
274 | + expect(desc('0 30 10-13 ? * WED,FRI')).to eq( | |
275 | + 'La 30 minute în fiecare oră, între 10:00 AM și 1:59 PM, numai miercuri și vineri') | |
276 | + end | |
277 | + | |
278 | + it 'seconds past the minute interval' do | |
279 | + expect(desc('10 0/5 * * * ?')).to eq('La secunda 10, la fiecare 5 minute') | |
280 | + end | |
281 | + | |
282 | + it 'between with interval' do | |
283 | + expect(desc('2-59/3 1,9,22 11-26 1-6 ?')).to eq( | |
284 | + 'La fiecare 3 minute, între minutele 02 și 59, la 1:00 AM, 9:00 AM și 10:00 PM, între zilele 11 și 26 a lunii, din ianuarie până în iunie') | |
285 | + end | |
286 | + | |
287 | + it 'recurring first of month' do | |
288 | + expect(desc('0 0 6 1/1 * ?')).to eq('La 6:00 AM') | |
289 | + end | |
290 | + | |
291 | + it 'minutes past the hour' do | |
292 | + expect(desc('0 5 0/1 * * ?')).to eq('La 05 minute în fiecare oră') | |
293 | + end | |
294 | + | |
295 | + it 'every past the hour' do | |
296 | + expect(desc('0 0,5,10,15,20,25,30,35,40,45,50,55 * ? * *')).to eq( | |
297 | + 'La 00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50 și 55 minute în fiecare oră') | |
298 | + end | |
299 | + | |
300 | + it 'every X minutes past the hour with interval' do | |
301 | + expect(desc('0 0-30/2 17 ? * MON-FRI')).to eq( | |
302 | + 'La fiecare 2 minute, între minutele 00 și 30, la 5:00 PM, de luni până vineri') | |
303 | + end | |
304 | + | |
305 | + it 'every X days with interval' do | |
306 | + expect(desc('30 7 1-L/2 * *')).to eq('La 7:30 AM, la fiecare 2 zile, între zilele 1 și ultima zi a lunii') | |
307 | + end | |
308 | + | |
309 | + it 'one year only with seconds' do | |
310 | + expect(desc('* * * * * * 2013')).to eq('În fiecare secundă, numai în 2013') | |
311 | + end | |
312 | + | |
313 | + it 'one year only without seconds' do | |
314 | + expect(desc('* * * * * 2013')).to eq('În fiecare minut, numai în 2013') | |
315 | + end | |
316 | + | |
317 | + it 'two years only' do | |
318 | + expect(desc('* * * * * 2013,2014')).to eq('În fiecare minut, numai în 2013 și 2014') | |
319 | + end | |
320 | + | |
321 | + it 'year range 2' do | |
322 | + expect(desc('23 12 * JAN-FEB * 2013-2014')).to eq('La 12:23 PM, din ianuarie până în februarie, din 2013 până în 2014') | |
323 | + end | |
324 | + | |
325 | + it 'year range 3' do | |
326 | + expect(desc('23 12 * JAN-MAR * 2013-2015')).to eq('La 12:23 PM, din ianuarie până în martie, din 2013 până în 2015') | |
327 | + end | |
328 | + | |
329 | + context 'multi part range seconds:' do | |
330 | + it 'multi part range seconds 2,4-5' do | |
331 | + expect(desc('2,4-5 1 * * *')).to eq('Între minutele 02,04 și 05, la 1:00 AM') | |
332 | + end | |
333 | + | |
334 | + it 'multi part range seconds 2,26-28' do | |
335 | + expect(desc('2,26-28 18 * * *')).to eq('Între minutele 02,26 și 28, la 6:00 PM') | |
336 | + end | |
337 | + end | |
338 | + | |
339 | + context 'minutes past the hour:' do | |
340 | + it 'minutes past the hour 5,10, midnight hour' do | |
341 | + expect(desc('5,10 0 * * *')).to eq('La 05 și 10 minute în fiecare oră, la 12:00 AM') | |
342 | + end | |
343 | + | |
344 | + it 'minutes past the hour 5,10' do | |
345 | + expect(desc('5,10 * * * *')).to eq('La 05 și 10 minute în fiecare oră') | |
346 | + end | |
347 | + | |
348 | + it 'minutes past the hour 5,10 day 2' do | |
349 | + expect(desc('5,10 * 2 * *')).to eq('La 05 și 10 minute în fiecare oră, în a 2-a zi a lunii') | |
350 | + end | |
351 | + | |
352 | + it 'minutes past the hour 5/10 day 2' do | |
353 | + expect(desc('5/10 * 2 * *')).to eq('La fiecare 10 minute, pornire la 05 minute în fiecare oră, în a 2-a zi a lunii') | |
354 | + end | |
355 | + end | |
356 | + | |
357 | + context 'seconds past the minute:' do | |
358 | + it 'seconds past the minute 5,6, midnight hour' do | |
359 | + expect(desc('5,6 0 0 * * *')).to eq('La secunda 5 și 6, la 12:00 AM') | |
360 | + end | |
361 | + | |
362 | + it 'seconds past the minute 5,6' do | |
363 | + expect(desc('5,6 0 * * * *')).to eq('La secunda 5 și 6') | |
364 | + end | |
365 | + | |
366 | + it 'seconds past the minute 5,6 at 1' do | |
367 | + expect(desc('5,6 0 1 * * *')).to eq('La secunda 5 și 6, la 1:00 AM') | |
368 | + end | |
369 | + | |
370 | + it 'seconds past the minute 5,6 day 2' do | |
371 | + expect(desc('5,6 0 * 2 * *')).to eq('La secunda 5 și 6, în a 2-a zi a lunii') | |
372 | + end | |
373 | + end | |
374 | + | |
375 | + context 'increments starting at X > 1:' do | |
376 | + it 'second increments' do | |
377 | + expect(desc('5/15 0 * * * *')).to eq('La fiecare 15 secunde, pornire la secunda 5') | |
378 | + end | |
379 | + | |
380 | + it 'minute increments' do | |
381 | + expect(desc('30/10 * * * *')).to eq('La fiecare 10 minute, pornire la 30 minute în fiecare oră') | |
382 | + end | |
383 | + | |
384 | + it 'hour increments' do | |
385 | + expect(desc('0 30 2/6 * * ?')).to eq('La 30 minute în fiecare oră, la fiecare 6 ore, pornire la 2:00 AM') | |
386 | + end | |
387 | + | |
388 | + it 'day of month increments' do | |
389 | + expect(desc('0 30 8 2/7 * *')).to eq('La 8:30 AM, la fiecare 7 zile, pornire în a 2-a zi a lunii') | |
390 | + end | |
391 | + | |
392 | + it 'day of week increments' do | |
393 | + expect(desc('0 30 11 * * 2/2')).to eq('La 11:30 AM, în fiecare 2 zile din săptămână, pornire de marți') | |
394 | + end | |
395 | + | |
396 | + it 'month increments' do | |
397 | + expect(desc('0 20 10 * 2/3 THU')).to eq('La 10:20 AM, numai joi, la fiecare 3 luni, pornire în februarie') | |
398 | + end | |
399 | + | |
400 | + it 'year increments' do | |
401 | + expect(desc('0 0 0 1 MAR * 2010/5')).to eq('La 12:00 AM, în a 1-a zi a lunii, numai în martie, la fiecare 5 ani, pornire în 2010') | |
402 | + end | |
403 | + end | |
404 | + end | |
405 | +end | ... | ... |
1 | +++ a/spec/exp_descriptor_ru_spec.rb | |
... | ... | @@ -0,0 +1,405 @@ |
1 | +# encoding: utf-8 | |
2 | +require 'cronex' | |
3 | + | |
4 | +module Cronex | |
5 | + describe ExpressionDescriptor do | |
6 | + | |
7 | + def desc(expression, opts = {}) | |
8 | + opts[:locale] = 'ru' | |
9 | + Cronex::ExpressionDescriptor.new(expression, opts).description | |
10 | + end | |
11 | + | |
12 | + let(:opts) { { zero_based_dow: false } } | |
13 | + | |
14 | + it 'every second' do | |
15 | + expect(desc('* * * * * *')).to eq('Каждую секунду') | |
16 | + end | |
17 | + | |
18 | + it 'every 45 seconds' do | |
19 | + expect(desc('*/45 * * * * *')).to eq('Каждые 45 секунд') | |
20 | + end | |
21 | + | |
22 | + it 'minute span' do | |
23 | + expect(desc('0-10 11 * * *')).to eq('Каждую минуту с 11:00 AM по 11:10 AM') | |
24 | + end | |
25 | + | |
26 | + context 'every minute' do | |
27 | + it 'every minute' do | |
28 | + expect(desc('* * * * *')).to eq('Каждую минуту') | |
29 | + end | |
30 | + | |
31 | + it 'every minute */1' do | |
32 | + expect(desc('*/1 * * * *')).to eq('Каждую минуту') | |
33 | + end | |
34 | + | |
35 | + it 'every minute 0 0/1' do | |
36 | + expect(desc('0 0/1 * * * ?')).to eq('Каждую минуту') | |
37 | + end | |
38 | + end | |
39 | + | |
40 | + context 'every X minutes:' do | |
41 | + it 'every 5 minutes' do | |
42 | + expect(desc('*/5 * * * *')).to eq('Каждые 5 минут') | |
43 | + end | |
44 | + | |
45 | + it 'every 5 minutes at Midnight' do | |
46 | + expect(desc('*/5 0 * * *')).to eq('Каждые 5 минут, в 12:00 AM') | |
47 | + end | |
48 | + | |
49 | + it 'every 5 minutes 0 */5' do | |
50 | + expect(desc('0 */5 * * * *')).to eq('Каждые 5 минут') | |
51 | + end | |
52 | + | |
53 | + it 'every 10 minutes 0 0/10' do | |
54 | + expect(desc('0 0/10 * * * ?')).to eq('Каждые 10 минут') | |
55 | + end | |
56 | + end | |
57 | + | |
58 | + context 'every hour:' do | |
59 | + it 'every hour 0 0' do | |
60 | + expect(desc('0 0 * * * ?')).to eq('Каждый час') | |
61 | + end | |
62 | + | |
63 | + it 'every hour 0 0 0/1' do | |
64 | + expect(desc('0 0 0/1 * * ?')).to eq('Каждый час') | |
65 | + end | |
66 | + end | |
67 | + | |
68 | + context 'daily:' do | |
69 | + it 'daily at /\d\d/:/\d\d/' do | |
70 | + expect(desc('30 11 * * *')).to eq('В 11:30 AM') | |
71 | + end | |
72 | + | |
73 | + it 'daily at /\d/:/\d/' do | |
74 | + expect(desc('9 8 * * *')).to eq('В 8:09 AM') | |
75 | + end | |
76 | + | |
77 | + it 'daily at /0[89]/:/0[89]/' do | |
78 | + expect(desc('09 08 * * *')).to eq('В 8:09 AM') | |
79 | + end | |
80 | + | |
81 | + it 'daily at /0[1-7]/ /0[1-7/' do | |
82 | + expect(desc('02 01 * * *')).to eq('В 1:02 AM') | |
83 | + end | |
84 | + end | |
85 | + | |
86 | + context 'time of day certain days of week:' do | |
87 | + it 'time of day on MON-FRI' do | |
88 | + expect(desc('0 23 ? * MON-FRI')).to eq('В 11:00 PM, понедельник - пятница') | |
89 | + end | |
90 | + | |
91 | + it 'time of day on 1-5' do | |
92 | + expect(desc('30 11 * * 1-5')).to eq('В 11:30 AM, понедельник - пятница') | |
93 | + end | |
94 | + end | |
95 | + | |
96 | + it 'one month only' do | |
97 | + expect(desc('* * * 3 *')).to eq('Каждую минуту, только март') | |
98 | + end | |
99 | + | |
100 | + it 'two months only' do | |
101 | + expect(desc('* * * 3,6 *')).to eq('Каждую минуту, только март и июнь') | |
102 | + end | |
103 | + | |
104 | + it 'two times each afternoon' do | |
105 | + expect(desc('30 14,16 * * *')).to eq('В 2:30 PM и 4:30 PM') | |
106 | + end | |
107 | + | |
108 | + it 'three times daily' do | |
109 | + expect(desc('30 6,14,16 * * *')).to eq('В 6:30 AM, 2:30 PM и 4:30 PM') | |
110 | + end | |
111 | + | |
112 | + context 'once a week:' do | |
113 | + it 'once a week 0' do | |
114 | + expect(desc('46 9 * * 0')).to eq('В 9:46 AM, только воскресенье') | |
115 | + end | |
116 | + | |
117 | + it 'once a week SUN' do | |
118 | + expect(desc('46 9 * * SUN')).to eq('В 9:46 AM, только воскресенье') | |
119 | + end | |
120 | + | |
121 | + it 'once a week 7' do | |
122 | + expect(desc('46 9 * * 7')).to eq('В 9:46 AM, только воскресенье') | |
123 | + end | |
124 | + | |
125 | + it 'once a week 1' do | |
126 | + expect(desc('46 9 * * 1')).to eq('В 9:46 AM, только понедельник') | |
127 | + end | |
128 | + | |
129 | + it 'once a week 6' do | |
130 | + expect(desc('46 9 * * 6')).to eq('В 9:46 AM, только суббота') | |
131 | + end | |
132 | + end | |
133 | + | |
134 | + context 'once a week non zero based:' do | |
135 | + it 'once a week 1' do | |
136 | + expect(desc('46 9 * * 1', opts)).to eq('В 9:46 AM, только воскресенье') | |
137 | + end | |
138 | + | |
139 | + it 'once a week SUN' do | |
140 | + expect(desc('46 9 * * SUN', opts)).to eq('В 9:46 AM, только воскресенье') | |
141 | + end | |
142 | + | |
143 | + it 'once a week 2' do | |
144 | + expect(desc('46 9 * * 2', opts)).to eq('В 9:46 AM, только понедельник') | |
145 | + end | |
146 | + | |
147 | + it 'once a week 7' do | |
148 | + expect(desc('46 9 * * 7', opts)).to eq('В 9:46 AM, только суббота') | |
149 | + end | |
150 | + end | |
151 | + | |
152 | + context 'twice a week:' do | |
153 | + it 'twice a week 1,2' do | |
154 | + expect(desc('46 9 * * 1,2')).to eq('В 9:46 AM, только понедельник и вторник') | |
155 | + end | |
156 | + | |
157 | + it 'twice a week MON,TUE' do | |
158 | + expect(desc('46 9 * * MON,TUE')).to eq('В 9:46 AM, только понедельник и вторник') | |
159 | + end | |
160 | + | |
161 | + it 'twice a week 0,6' do | |
162 | + expect(desc('46 9 * * 0,6')).to eq('В 9:46 AM, только воскресенье и суббота') | |
163 | + end | |
164 | + | |
165 | + it 'twice a week 6,7' do | |
166 | + expect(desc('46 9 * * 6,7')).to eq('В 9:46 AM, только суббота и воскресенье') | |
167 | + end | |
168 | + end | |
169 | + | |
170 | + context 'twice a week non zero based:' do | |
171 | + it 'twice a week 1,2' do | |
172 | + expect(desc('46 9 * * 1,2', opts)).to eq('В 9:46 AM, только воскресенье и понедельник') | |
173 | + end | |
174 | + | |
175 | + it 'twice a week SUN,MON' do | |
176 | + expect(desc('46 9 * * SUN,MON', opts)).to eq('В 9:46 AM, только воскресенье и понедельник') | |
177 | + end | |
178 | + | |
179 | + it 'twice a week 6,7' do | |
180 | + expect(desc('46 9 * * 6,7', opts)).to eq('В 9:46 AM, только пятница и суббота') | |
181 | + end | |
182 | + end | |
183 | + | |
184 | + it 'day of month' do | |
185 | + expect(desc('23 12 15 * *')).to eq('В 12:23 PM, 15 день месяца') | |
186 | + end | |
187 | + | |
188 | + it 'day of month with day of week' do | |
189 | + expect(desc('23 12 15 * SUN')).to eq('В 12:23 PM, 15 день месяца, только воскресенье') | |
190 | + end | |
191 | + | |
192 | + it 'month name' do | |
193 | + expect(desc('23 12 * JAN *')).to eq('В 12:23 PM, только январь') | |
194 | + end | |
195 | + | |
196 | + it 'day of month with question mark' do | |
197 | + expect(desc('23 12 ? JAN *')).to eq('В 12:23 PM, только январь') | |
198 | + end | |
199 | + | |
200 | + it 'month name range 2' do | |
201 | + expect(desc('23 12 * JAN-FEB *')).to eq('В 12:23 PM, январь - февраль') | |
202 | + end | |
203 | + | |
204 | + it 'month name range 3' do | |
205 | + expect(desc('23 12 * JAN-MAR *')).to eq('В 12:23 PM, январь - март') | |
206 | + end | |
207 | + | |
208 | + it 'day of week name' do | |
209 | + expect(desc('23 12 * * SUN')).to eq('В 12:23 PM, только воскресенье') | |
210 | + end | |
211 | + | |
212 | + context 'day of week range:' do | |
213 | + it 'day of week range MON-FRI' do | |
214 | + expect(desc('*/5 15 * * MON-FRI')).to eq('Каждые 5 минут, в 3:00 PM, понедельник - пятница') | |
215 | + end | |
216 | + | |
217 | + it 'day of week range 0-6' do | |
218 | + expect(desc('*/5 15 * * 0-6')).to eq('Каждые 5 минут, в 3:00 PM, воскресенье - суббота') | |
219 | + end | |
220 | + | |
221 | + it 'day of week range 6-7' do | |
222 | + expect(desc('*/5 15 * * 6-7')).to eq('Каждые 5 минут, в 3:00 PM, суббота - воскресенье') | |
223 | + end | |
224 | + end | |
225 | + | |
226 | + context 'day of week once in month:' do | |
227 | + it 'day of week once MON#3' do | |
228 | + expect(desc('* * * * MON#3')).to eq('Каждую минуту, в третий понедельник месяца') | |
229 | + end | |
230 | + | |
231 | + it 'day of week once 0#3' do | |
232 | + expect(desc('* * * * 0#3')).to eq('Каждую минуту, в третий воскресенье месяца') | |
233 | + end | |
234 | + end | |
235 | + | |
236 | + context 'last day of week of the month:' do | |
237 | + it 'last day of week 4L' do | |
238 | + expect(desc('* * * * 4L')).to eq('Каждую минуту, в последний четверг месяца') | |
239 | + end | |
240 | + | |
241 | + it 'last day of week 0L' do | |
242 | + expect(desc('* * * * 0L')).to eq('Каждую минуту, в последний воскресенье месяца') | |
243 | + end | |
244 | + end | |
245 | + | |
246 | + context 'last day of the month:' do | |
247 | + it 'on the last day of the month' do | |
248 | + expect(desc('*/5 * L JAN *')).to eq('Каждые 5 минут, в последний день месяца, только январь') | |
249 | + end | |
250 | + | |
251 | + it 'between a day and last day of the month' do | |
252 | + expect(desc('*/5 * 23-L JAN *')).to eq('Каждые 5 минут, между 23 днем и последним днем месяца, только январь') | |
253 | + end | |
254 | + end | |
255 | + | |
256 | + it 'time of day with seconds' do | |
257 | + expect(desc('30 02 14 * * *')).to eq('В 2:02:30 PM') | |
258 | + end | |
259 | + | |
260 | + it 'second intervals' do | |
261 | + expect(desc('5-10 * * * * *')).to eq('Секунды с 5 по 10') | |
262 | + end | |
263 | + | |
264 | + it 'second minutes hours intervals' do | |
265 | + expect(desc('5-10 30-35 10-12 * * *')).to eq( | |
266 | + 'Секунды с 5 по 10, минуты с 30 по 35, между 10:00 AM и 12:59 PM') | |
267 | + end | |
268 | + | |
269 | + it 'every 5 minutes at 30 seconds' do | |
270 | + expect(desc('30 */5 * * * *')).to eq('В 30 секунд, каждые 5 минут') | |
271 | + end | |
272 | + | |
273 | + it 'minutes past the hour range' do | |
274 | + expect(desc('0 30 10-13 ? * WED,FRI')).to eq( | |
275 | + 'В 30 минут часа, между 10:00 AM и 1:59 PM, только среда и пятница') | |
276 | + end | |
277 | + | |
278 | + it 'seconds past the minute interval' do | |
279 | + expect(desc('10 0/5 * * * ?')).to eq('В 10 секунд, каждые 5 минут') | |
280 | + end | |
281 | + | |
282 | + it 'between with interval' do | |
283 | + expect(desc('2-59/3 1,9,22 11-26 1-6 ?')).to eq( | |
284 | + 'Каждые 3 минут, минуты с 02 по 59, в 1:00 AM, 9:00 AM и 10:00 PM, между 11 днем и 26 днем месяца, январь - июнь') | |
285 | + end | |
286 | + | |
287 | + it 'recurring first of month' do | |
288 | + expect(desc('0 0 6 1/1 * ?')).to eq('В 6:00 AM') | |
289 | + end | |
290 | + | |
291 | + it 'minutes past the hour' do | |
292 | + expect(desc('0 5 0/1 * * ?')).to eq('В 05 минут часа') | |
293 | + end | |
294 | + | |
295 | + it 'every past the hour' do | |
296 | + expect(desc('0 0,5,10,15,20,25,30,35,40,45,50,55 * ? * *')).to eq( | |
297 | + 'В 00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50 и 55 минут часа') | |
298 | + end | |
299 | + | |
300 | + it 'every X minutes past the hour with interval' do | |
301 | + expect(desc('0 0-30/2 17 ? * MON-FRI')).to eq( | |
302 | + 'Каждые 2 минут, минуты с 00 по 30, в 5:00 PM, понедельник - пятница') | |
303 | + end | |
304 | + | |
305 | + it 'every X days with interval' do | |
306 | + expect(desc('30 7 1-L/2 * *')).to eq('В 7:30 AM, каждые 2 дня(ей), между 1 днем и последним днем месяца') | |
307 | + end | |
308 | + | |
309 | + it 'one year only with seconds' do | |
310 | + expect(desc('* * * * * * 2013')).to eq('Каждую секунду, только 2013') | |
311 | + end | |
312 | + | |
313 | + it 'one year only without seconds' do | |
314 | + expect(desc('* * * * * 2013')).to eq('Каждую минуту, только 2013') | |
315 | + end | |
316 | + | |
317 | + it 'two years only' do | |
318 | + expect(desc('* * * * * 2013,2014')).to eq('Каждую минуту, только 2013 и 2014') | |
319 | + end | |
320 | + | |
321 | + it 'year range 2' do | |
322 | + expect(desc('23 12 * JAN-FEB * 2013-2014')).to eq('В 12:23 PM, январь - февраль, 2013 - 2014') | |
323 | + end | |
324 | + | |
325 | + it 'year range 3' do | |
326 | + expect(desc('23 12 * JAN-MAR * 2013-2015')).to eq('В 12:23 PM, январь - март, 2013 - 2015') | |
327 | + end | |
328 | + | |
329 | + context 'multi part range seconds:' do | |
330 | + it 'multi part range seconds 2,4-5' do | |
331 | + expect(desc('2,4-5 1 * * *')).to eq('Минуты с 02,04 по 05, в 1:00 AM') | |
332 | + end | |
333 | + | |
334 | + it 'multi part range seconds 2,26-28' do | |
335 | + expect(desc('2,26-28 18 * * *')).to eq('Минуты с 02,26 по 28, в 6:00 PM') | |
336 | + end | |
337 | + end | |
338 | + | |
339 | + context 'minutes past the hour:' do | |
340 | + it 'minutes past the hour 5,10, midnight hour' do | |
341 | + expect(desc('5,10 0 * * *')).to eq('В 05 и 10 минут часа, в 12:00 AM') | |
342 | + end | |
343 | + | |
344 | + it 'minutes past the hour 5,10' do | |
345 | + expect(desc('5,10 * * * *')).to eq('В 05 и 10 минут часа') | |
346 | + end | |
347 | + | |
348 | + it 'minutes past the hour 5,10 day 2' do | |
349 | + expect(desc('5,10 * 2 * *')).to eq('В 05 и 10 минут часа, 2 день месяца') | |
350 | + end | |
351 | + | |
352 | + it 'minutes past the hour 5/10 day 2' do | |
353 | + expect(desc('5/10 * 2 * *')).to eq('Каждые 10 минут, начало в 05 минут часа, 2 день месяца') | |
354 | + end | |
355 | + end | |
356 | + | |
357 | + context 'seconds past the minute:' do | |
358 | + it 'seconds past the minute 5,6, midnight hour' do | |
359 | + expect(desc('5,6 0 0 * * *')).to eq('В 5 и 6 секунд, в 12:00 AM') | |
360 | + end | |
361 | + | |
362 | + it 'seconds past the minute 5,6' do | |
363 | + expect(desc('5,6 0 * * * *')).to eq('В 5 и 6 секунд') | |
364 | + end | |
365 | + | |
366 | + it 'seconds past the minute 5,6 at 1' do | |
367 | + expect(desc('5,6 0 1 * * *')).to eq('В 5 и 6 секунд, в 1:00 AM') | |
368 | + end | |
369 | + | |
370 | + it 'seconds past the minute 5,6 day 2' do | |
371 | + expect(desc('5,6 0 * 2 * *')).to eq('В 5 и 6 секунд, 2 день месяца') | |
372 | + end | |
373 | + end | |
374 | + | |
375 | + context 'increments starting at X > 1:' do | |
376 | + it 'second increments' do | |
377 | + expect(desc('5/15 0 * * * *')).to eq('Каждые 15 секунд, начало в 5 секунд') | |
378 | + end | |
379 | + | |
380 | + it 'minute increments' do | |
381 | + expect(desc('30/10 * * * *')).to eq('Каждые 10 минут, начало в 30 минут часа') | |
382 | + end | |
383 | + | |
384 | + it 'hour increments' do | |
385 | + expect(desc('0 30 2/6 * * ?')).to eq('В 30 минут часа, каждые 6 часов, начало в 2:00 AM') | |
386 | + end | |
387 | + | |
388 | + it 'day of month increments' do | |
389 | + expect(desc('0 30 8 2/7 * *')).to eq('В 8:30 AM, каждые 7 дня(ей), начало 2 день месяца') | |
390 | + end | |
391 | + | |
392 | + it 'day of week increments' do | |
393 | + expect(desc('0 30 11 * * 2/2')).to eq('В 11:30 AM, каждые 2 дня(ей) недели, начало в вторник') | |
394 | + end | |
395 | + | |
396 | + it 'month increments' do | |
397 | + expect(desc('0 20 10 * 2/3 THU')).to eq('В 10:20 AM, только четверг, каждые 3 месяцев, начало в февраль') | |
398 | + end | |
399 | + | |
400 | + it 'year increments' do | |
401 | + expect(desc('0 0 0 1 MAR * 2010/5')).to eq('В 12:00 AM, 1 день месяца, только март, каждые 5 лет, начало в 2010') | |
402 | + end | |
403 | + end | |
404 | + end | |
405 | +end | ... | ... |
1 | +++ a/spec/spec_helper.rb | |
... | ... | @@ -0,0 +1,11 @@ |
1 | +require 'rspec' | |
2 | + | |
3 | +RSpec.configure do |config| | |
4 | + config.expect_with :rspec do |c| | |
5 | + c.syntax = :expect | |
6 | + end | |
7 | + | |
8 | + def desc(expression, opts = {}) | |
9 | + Cronex::ExpressionDescriptor.new(expression, opts).description | |
10 | + end | |
11 | +end | ... | ... |