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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 | \ No newline at end of file | 77 | \ No newline at end of file |
1 | +++ a/resources/resources_zh-TW.yml | ||
@@ -0,0 +1,76 @@ | @@ -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 | \ No newline at end of file | 77 | \ No newline at end of file |
1 | +++ a/spec/casing_spec.rb | ||
@@ -0,0 +1,22 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 @@ | @@ -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 |