cronex 0.7.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 29978d178bd1bb48a3a10583b197d09a0bd768ea
4
- data.tar.gz: 7efd313aecf280cfe7d6817b392cc51e571a7c29
3
+ metadata.gz: b071e718281eae3aa398857c94a82313f7c86cbc
4
+ data.tar.gz: 11072364556f0d7b2649dca6d4ddde874facba88
5
5
  SHA512:
6
- metadata.gz: fa456bfec078001cc6b12cc6c7d950e6dd1b8746d69f7341f3ffa6a2834add6ac72ebdb96364713f9d0818eab7dd1c6e6a857cf281a88c7447b1079ac75b68b6
7
- data.tar.gz: b4dd39b0fce8599164262e26000bad29b2eeecfc964e82675f353c6af1a886cec1c7f8ba22a494e195fb5ceaa3182978de2306eff54cc73cbc5f4563e08f4bdf
6
+ metadata.gz: b17652914797dde9564a267cc9fe9a98355299a17850646a0a97f40bd0d4df08e95ed1646a46ec24098262cad567a1fbef0df597e1ad068fd603ef186fffe61c
7
+ data.tar.gz: 272be7fae9d337fde1e20e2e6e1e10b4d52b578df067b03a7add886b5b5d20264f06dc6efb8ca6d651d6c0fc3fc9e75ca08bd962dadd0748996d5fca41b96fd5
@@ -1,47 +1,56 @@
1
- Encoding:
1
+ Style/Encoding:
2
2
  Enabled: false
3
3
 
4
- AmbiguousOperator:
4
+ Lint/AmbiguousOperator:
5
5
  Enabled: false
6
6
 
7
- CaseIndentation:
7
+ Layout/CaseIndentation:
8
8
  Enabled: false
9
9
 
10
- CyclomaticComplexity:
10
+ Metrics/CyclomaticComplexity:
11
11
  Enabled: false
12
12
  Max: 10
13
13
 
14
- PerceivedComplexity:
14
+ Metrics/PerceivedComplexity:
15
15
  Enabled: false
16
16
  Max: 10
17
17
 
18
- Documentation:
18
+ Style/Documentation:
19
19
  Enabled: false
20
20
 
21
- EmptyLinesAroundBody:
21
+ Layout/EmptyLinesAroundBlockBody:
22
22
  Enabled: false
23
23
 
24
- ClassLength:
24
+ Layout/EmptyLinesAroundClassBody:
25
25
  Enabled: false
26
26
 
27
- LineLength:
27
+ Layout/EmptyLinesAroundModuleBody:
28
+ Enabled: false
29
+
30
+ Metrics/ClassLength:
31
+ Enabled: false
32
+
33
+ Style/FrozenStringLiteralComment:
34
+ Enabled: false
35
+
36
+ Layout/LineLength:
28
37
  Enabled: true
29
38
  Max: 160
30
39
 
31
- MethodLength:
40
+ Metrics/MethodLength:
32
41
  Enabled: false
33
42
 
34
- ModuleFunction:
43
+ Style/ModuleFunction:
35
44
  Enabled: false
36
45
 
37
- NestedTernaryOperator:
46
+ Style/NestedTernaryOperator:
38
47
  Enabled: false
39
48
 
40
- RaiseArgs:
49
+ Style/RaiseArgs:
41
50
  Enabled: false
42
51
 
43
- RescueModifier:
52
+ Style/RescueModifier:
44
53
  Enabled: false
45
54
 
46
- UnusedMethodArgument:
55
+ Lint/UnusedMethodArgument:
47
56
  Enabled: false
@@ -1,3 +1,9 @@
1
1
  language: ruby
2
+
3
+ cache: bundler
4
+
2
5
  rvm:
3
- - 2.2
6
+ - 2.3
7
+ - 2.4
8
+ - 2.5
9
+ - 2.6
@@ -1,3 +1,18 @@
1
+ ### [0.10.0] - 2020-05-26
2
+ * Move locale and timezone arguments to options
3
+
4
+ ### [0.9.2] - 2020-04-24
5
+ * Add italian locale
6
+
7
+ ### [0.9.1] - 2019-11-26
8
+ * Update tzinfo dependency
9
+
10
+ ### [0.9.0] - 2019-04-21
11
+ * Add german locale
12
+
13
+ ### [0.8.0] - 2019-04-18
14
+ * Add support for timezones
15
+
1
16
  ### [0.7.0] - 2018-11-22
2
17
  * Include day of week when day of month is specified
3
18
 
data/README.md CHANGED
@@ -16,6 +16,7 @@ Original Author & Credit: Brady Holt (http://www.geekytidbits.com).
16
16
  * Provides casing options (sentence, title, lower)
17
17
  * Support for non-standard non-zero-based week day numbers
18
18
  * Supports printing to locale specific human readable format
19
+ * Supports displaying times in specific timezones
19
20
 
20
21
  For a quick intro to cron see Quartz [Cron Tutorial](http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger).
21
22
 
@@ -24,6 +25,8 @@ For a quick intro to cron see Quartz [Cron Tutorial](http://www.quartz-scheduler
24
25
  * English
25
26
  * Brazilian
26
27
  * French
28
+ * German
29
+ * Italian
27
30
  * Romanian
28
31
  * Russian
29
32
 
@@ -58,9 +61,15 @@ Or install it yourself as:
58
61
 
59
62
  #### Localization
60
63
 
61
- Cronex::ExpressionDescriptor.new('30 2 * 2 1-5', {}, 'fr').description
64
+ Cronex::ExpressionDescriptor.new('30 2 * 2 1-5', locale: 'fr').description
62
65
  => À 2:30 AM, lundi à vendredi, seulement en février
63
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
+
64
73
  See spec tests for more examples.
65
74
 
66
75
  ### Contributing
@@ -20,8 +20,9 @@ Gem::Specification.new do |spec|
20
20
  spec.test_files = spec.files.grep(/^(test|spec|features)\//)
21
21
  spec.require_paths = ['lib']
22
22
 
23
+ spec.add_runtime_dependency 'tzinfo'
23
24
  spec.add_runtime_dependency 'unicode'
24
25
  spec.add_development_dependency 'pry', '~> 0.10'
25
- spec.add_development_dependency 'rake', '~> 10.1'
26
+ spec.add_development_dependency 'rake', '>= 12.3.3'
26
27
  spec.add_development_dependency 'rspec', '~> 3.1'
27
28
  end
@@ -1,7 +1,7 @@
1
1
  module Cronex
2
2
  class HoursDescription < Description
3
- def single_item_description(expression)
4
- Cronex::Utils.format_time(expression, '0')
3
+ def single_item_description(expression, timezone = 'UTC')
4
+ Cronex::Utils.format_time(expression, '0', '', timezone)
5
5
  end
6
6
 
7
7
  def interval_description_format(expression)
@@ -12,18 +12,21 @@ module Cronex
12
12
  verbose: false,
13
13
  zero_based_dow: true,
14
14
  use_24_hour_time_format: false,
15
- throw_exception_on_parse_error: true
15
+ throw_exception_on_parse_error: true,
16
+ locale: nil,
17
+ timezone: nil
16
18
  }
17
19
 
18
20
  class ExpressionDescriptor
19
- attr_accessor :expression, :expression_parts, :options, :parsed, :resources
21
+ attr_accessor :expression, :expression_parts, :options, :parsed, :resources, :timezone
20
22
 
21
- def initialize(expression, options = {}, locale = nil)
23
+ def initialize(expression, options = {})
22
24
  @expression = expression
23
25
  @options = CRONEX_OPTS.merge(options)
24
26
  @expression_parts = []
25
27
  @parsed = false
26
- @resources = Cronex::Resource.new(locale)
28
+ @resources = Cronex::Resource.new(@options[:locale])
29
+ @timezone = @options[:timezone] || 'UTC'
27
30
  end
28
31
 
29
32
  def to_hash
@@ -129,19 +132,19 @@ module Cronex
129
132
  description = ''
130
133
  if [sec_exp, min_exp, hour_exp].all? { |exp| !Cronex::Utils.include_any?(exp, SPECIAL_CHARS) }
131
134
  # specific time of day (i.e. 10 14)
132
- description += resources.get('at') + ' ' + Cronex::Utils.format_time(hour_exp, min_exp, sec_exp)
135
+ description += resources.get('at') + ' ' + Cronex::Utils.format_time(hour_exp, min_exp, sec_exp, timezone)
133
136
  elsif min_exp.include?('-') && !min_exp.include?('/') && !min_exp.include?(',') && !Cronex::Utils.include_any?(hour_exp, SPECIAL_CHARS)
134
137
  # Minute range in single hour (e.g. 0-10 11)
135
138
  min_parts = min_exp.split('-')
136
139
  description += format(
137
140
  resources.get('every_minute_between'),
138
- Cronex::Utils.format_time(hour_exp, min_parts[0]),
139
- Cronex::Utils.format_time(hour_exp, min_parts[1]))
141
+ Cronex::Utils.format_time(hour_exp, min_parts[0], '', timezone),
142
+ Cronex::Utils.format_time(hour_exp, min_parts[1], '', timezone))
140
143
  elsif hour_exp.include?(',') && !Cronex::Utils.include_any?(min_exp, SPECIAL_CHARS)
141
144
  # Hours list with single minute (e.g. 30 6,14,16)
142
145
  hour_parts = hour_exp.split(',')
143
146
  description += resources.get('at')
144
- h_parts = hour_parts.map { |part| ' ' + Cronex::Utils.format_time(part, min_exp) }
147
+ h_parts = hour_parts.map { |part| ' ' + Cronex::Utils.format_time(part, min_exp, '', timezone) }
145
148
  description += h_parts[0...-1].join(',') + ' ' + resources.get('and') + h_parts.last
146
149
  else
147
150
  sec_desc = seconds_description(expression_parts)
@@ -1,3 +1,5 @@
1
+ require 'tzinfo'
2
+
1
3
  module Cronex
2
4
  module Utils
3
5
  extend self
@@ -32,18 +34,14 @@ module Cronex
32
34
  end
33
35
  end
34
36
 
35
- def format_time(hour_expression, minute_expression, second_expression = '')
37
+ def format_time(hour_expression, minute_expression, second_expression = '', timezone = 'UTC')
36
38
  hour = integer(hour_expression)
37
- period = hour >= 12 ? 'PM' : 'AM'
38
- hour -= 12 if hour > 12
39
39
  minute = integer(minute_expression)
40
- minute = format('%02d', minute)
41
- second = ''
42
- if present?(second_expression)
43
- second = integer(second_expression)
44
- second = ':' + format('%02d', second)
45
- end
46
- format('%s:%s%s %s', hour, minute, second, period)
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
47
45
  end
48
46
  end
49
47
  end
@@ -1,3 +1,3 @@
1
1
  module Cronex
2
- VERSION = '0.7.0'
2
+ VERSION = '0.10.0'
3
3
  end
@@ -0,0 +1,75 @@
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
+ first_weekday: 'Erster Wochentag'
20
+ weekday_nearest_day: 'Wochentag zum nächsten Tag %s'
21
+ starting: 'beginnend'
22
+ only_on: 'nur an %s'
23
+ only_in: 'nur in %s'
24
+ every_x_seconds: 'Alle %s Sekunden'
25
+ every_minute_between: 'Jede Minute zwischen %s und %s'
26
+ every_second: 'Jede Sekunde'
27
+ every_minute: 'Jede Minute'
28
+ every_1_minute: 'Jede 1. Minute'
29
+ every_hour: 'Jede Stunde'
30
+ every_1_hour: 'Jede 1. Stunde'
31
+ every_day: 'Jeden Tag'
32
+ every_1_day: 'Jeden 1. Tag'
33
+ every_year: 'Jedes Jahr'
34
+ every_x: 'Alle %s'
35
+ at_x: 'um %s'
36
+ on_x: 'an %s'
37
+ in_x: 'in %s'
38
+ first: ersten
39
+ second: zweiten
40
+ third: dritten
41
+ fourth: vierten
42
+ fifth: fünften
43
+ time_pm: PM
44
+ time_am: AM
45
+ and: und
46
+ at: Um
47
+ day: Tag
48
+ days: Tagen
49
+ hour: Stunde
50
+ hours: Stunden
51
+ minute: Minute
52
+ minutes: Minuten
53
+ month: Monat
54
+ months: Monaten
55
+ year: Jahr
56
+ years: Jahren
57
+ monday: Montag
58
+ tuesday: Dienstag
59
+ wednesday: Mittwoch
60
+ thursday: Donnerstag
61
+ friday: Freitag
62
+ saturday: Samstag
63
+ sunday: Sonntag
64
+ january: Januar
65
+ february: Februar
66
+ march: März
67
+ april: April
68
+ may: Mai
69
+ june: Juni
70
+ july: Juli
71
+ august: August
72
+ september: September
73
+ october: Oktober
74
+ november: November
75
+ december: Dezember
@@ -0,0 +1,75 @@
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 giorno %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
+ first_weekday: 'il primo giorno della settimana lavorativa'
20
+ weekday_nearest_day: 'il prossimo giorno %s della settimana lavorativa'
21
+ starting: 'a partire da'
22
+ only_on: 'solo di %s'
23
+ only_in: 'solo a(nel) %s'
24
+ every_x_seconds: 'ogni %s secondi'
25
+ every_minute_between: 'ogni minuto tra le %s e le %s'
26
+ every_second: 'ogni secondo'
27
+ every_minute: 'ogni minuto'
28
+ every_1_minute: 'ogni minuto'
29
+ every_hour: 'ogni ora'
30
+ every_1_hour: 'ogni ora'
31
+ every_day: 'ogni giorno'
32
+ every_1_day: 'ogni giorno'
33
+ every_year: 'ogni anno'
34
+ every_x: 'ogni %s'
35
+ at_x: 'alle(ai) %s'
36
+ on_x: 'il %s'
37
+ in_x: '%s'
38
+ first: primo
39
+ second: secondo
40
+ third: terzo
41
+ fourth: quarto
42
+ fifth: quinto
43
+ time_pm: pomeriggio
44
+ time_am: mattino
45
+ and: e
46
+ at: alle(ai)
47
+ day: giorno
48
+ days: giorni
49
+ hour: ora
50
+ hours: ore
51
+ minute: minuto
52
+ minutes: minuti
53
+ month: mese
54
+ months: mesi
55
+ year: anno
56
+ years: anni
57
+ monday: lunedì
58
+ tuesday: martedì
59
+ wednesday: mercoledì
60
+ thursday: giovedì
61
+ friday: venerdì
62
+ saturday: sabato
63
+ sunday: domenica
64
+ january: gennaio
65
+ february: febbraio
66
+ march: marzo
67
+ april: aprile
68
+ may: maggio
69
+ june: giugno
70
+ july: luglio
71
+ august: agosto
72
+ september: settembre
73
+ october: ottobre
74
+ november: novembre
75
+ december: dicembre
@@ -0,0 +1,383 @@
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 minute 0 */5' do
46
+ expect(desc('0 */5 * * * *')).to eq('Alle 5 Minuten')
47
+ end
48
+
49
+ it 'every 10 minutes 0 0/10' do
50
+ expect(desc('0 0/10 * * * ?')).to eq('Alle 10 Minuten')
51
+ end
52
+ end
53
+
54
+ context 'every hour:' do
55
+ it 'every hour 0 0' do
56
+ expect(desc('0 0 * * * ?')).to eq('Jede Stunde')
57
+ end
58
+
59
+ it 'every hour 0 0 0/1' do
60
+ expect(desc('0 0 0/1 * * ?')).to eq('Jede Stunde')
61
+ end
62
+ end
63
+
64
+ context 'daily:' do
65
+ it 'daily at /\d\d/:/\d\d/' do
66
+ expect(desc('30 11 * * *')).to eq('Um 11:30 AM')
67
+ end
68
+
69
+ it 'daily at /\d/:/\d/' do
70
+ expect(desc('9 8 * * *')).to eq('Um 8:09 AM')
71
+ end
72
+
73
+ it 'daily at /0[89]/:/0[89]/' do
74
+ expect(desc('09 08 * * *')).to eq('Um 8:09 AM')
75
+ end
76
+
77
+ it 'daily at /0[1-7]/ /0[1-7/' do
78
+ expect(desc('02 01 * * *')).to eq('Um 1:02 AM')
79
+ end
80
+ end
81
+
82
+ context 'time of day certain days of week:' do
83
+ it 'time of day on MON-FRI' do
84
+ expect(desc('0 23 ? * MON-FRI')).to eq('Um 11:00 PM, Montag bis Freitag')
85
+ end
86
+
87
+ it 'time of day on 1-5' do
88
+ expect(desc('30 11 * * 1-5')).to eq('Um 11:30 AM, Montag bis Freitag')
89
+ end
90
+ end
91
+
92
+ it 'one month only' do
93
+ expect(desc('* * * 3 *')).to eq('Jede Minute, nur in März')
94
+ end
95
+
96
+ it 'two months only' do
97
+ expect(desc('* * * 3,6 *')).to eq('Jede Minute, nur in März und Juni')
98
+ end
99
+
100
+ it 'two times each afternoon' do
101
+ expect(desc('30 14,16 * * *')).to eq('Um 2:30 PM und 4:30 PM')
102
+ end
103
+
104
+ it 'three times daily' do
105
+ expect(desc('30 6,14,16 * * *')).to eq('Um 6:30 AM, 2:30 PM und 4:30 PM')
106
+ end
107
+
108
+ context 'once a week:' do
109
+ it 'once a week 0' do
110
+ expect(desc('46 9 * * 0')).to eq('Um 9:46 AM, nur an Sonntag')
111
+ end
112
+
113
+ it 'once a week SUN' do
114
+ expect(desc('46 9 * * SUN')).to eq('Um 9:46 AM, nur an Sonntag')
115
+ end
116
+
117
+ it 'once a week 7' do
118
+ expect(desc('46 9 * * 7')).to eq('Um 9:46 AM, nur an Sonntag')
119
+ end
120
+
121
+ it 'once a week 1' do
122
+ expect(desc('46 9 * * 1')).to eq('Um 9:46 AM, nur an Montag')
123
+ end
124
+
125
+ it 'once a week 6' do
126
+ expect(desc('46 9 * * 6')).to eq('Um 9:46 AM, nur an Samstag')
127
+ end
128
+ end
129
+
130
+ context 'once a week non zero based:' do
131
+ it 'once a week 1' do
132
+ expect(desc('46 9 * * 1', opts)).to eq('Um 9:46 AM, nur an Sonntag')
133
+ end
134
+
135
+ it 'once a week SUN' do
136
+ expect(desc('46 9 * * SUN', opts)).to eq('Um 9:46 AM, nur an Sonntag')
137
+ end
138
+
139
+ it 'once a week 2' do
140
+ expect(desc('46 9 * * 2', opts)).to eq('Um 9:46 AM, nur an Montag')
141
+ end
142
+
143
+ it 'once a week 7' do
144
+ expect(desc('46 9 * * 7', opts)).to eq('Um 9:46 AM, nur an Samstag')
145
+ end
146
+ end
147
+
148
+ context 'twice a week:' do
149
+ it 'twice a week 1,2' do
150
+ expect(desc('46 9 * * 1,2')).to eq('Um 9:46 AM, nur an Montag und Dienstag')
151
+ end
152
+
153
+ it 'twice a week MON,TUE' do
154
+ expect(desc('46 9 * * MON,TUE')).to eq('Um 9:46 AM, nur an Montag und Dienstag')
155
+ end
156
+
157
+ it 'twice a week 0,6' do
158
+ expect(desc('46 9 * * 0,6')).to eq('Um 9:46 AM, nur an Sonntag und Samstag')
159
+ end
160
+
161
+ it 'twice a week 6,7' do
162
+ expect(desc('46 9 * * 6,7')).to eq('Um 9:46 AM, nur an Samstag und Sonntag')
163
+ end
164
+ end
165
+
166
+ context 'twice a week non zero based:' do
167
+ it 'twice a week 1,2' do
168
+ expect(desc('46 9 * * 1,2', opts)).to eq('Um 9:46 AM, nur an Sonntag und Montag')
169
+ end
170
+
171
+ it 'twice a week SUN,MON' do
172
+ expect(desc('46 9 * * SUN,MON', opts)).to eq('Um 9:46 AM, nur an Sonntag und Montag')
173
+ end
174
+
175
+ it 'twice a week 6,7' do
176
+ expect(desc('46 9 * * 6,7', opts)).to eq('Um 9:46 AM, nur an Freitag und Samstag')
177
+ end
178
+ end
179
+
180
+ it 'day of month' do
181
+ expect(desc('23 12 15 * *')).to eq('Um 12:23 PM, am 15 Tag des Monats')
182
+ end
183
+
184
+ it 'day of month with day of week' do
185
+ expect(desc('23 12 15 * SUN')).to eq('Um 12:23 PM, am 15 Tag des Monats, nur an Sonntag')
186
+ end
187
+
188
+ it 'month name' do
189
+ expect(desc('23 12 * JAN *')).to eq('Um 12:23 PM, nur in Januar')
190
+ end
191
+
192
+ it 'day of month with question mark' do
193
+ expect(desc('23 12 ? JAN *')).to eq('Um 12:23 PM, nur in Januar')
194
+ end
195
+
196
+ it 'month name range 2' do
197
+ expect(desc('23 12 * JAN-FEB *')).to eq('Um 12:23 PM, Januar bis Februar')
198
+ end
199
+
200
+ it 'month name range 3' do
201
+ expect(desc('23 12 * JAN-MAR *')).to eq('Um 12:23 PM, Januar bis März')
202
+ end
203
+
204
+ it 'day of week name' do
205
+ expect(desc('23 12 * * SUN')).to eq('Um 12:23 PM, nur an Sonntag')
206
+ end
207
+
208
+ context 'day of week range:' do
209
+ it 'day of week range MON-FRI' do
210
+ expect(desc('*/5 15 * * MON-FRI')).to eq('Alle 5 Minuten, um 3:00 PM, Montag bis Freitag')
211
+ end
212
+
213
+ it 'day of week range 0-6' do
214
+ expect(desc('*/5 15 * * 0-6')).to eq('Alle 5 Minuten, um 3:00 PM, Sonntag bis Samstag')
215
+ end
216
+
217
+ it 'day of week range 6-7' do
218
+ expect(desc('*/5 15 * * 6-7')).to eq('Alle 5 Minuten, um 3:00 PM, Samstag bis Sonntag')
219
+ end
220
+ end
221
+
222
+ context 'day of week once in month:' do
223
+ it 'day of week once MON#3' do
224
+ expect(desc('* * * * MON#3')).to eq('Jede Minute, am dritten Montag des Monats')
225
+ end
226
+
227
+ it 'day of week once 0#3' do
228
+ expect(desc('* * * * 0#3')).to eq('Jede Minute, am dritten Sonntag des Monats')
229
+ end
230
+ end
231
+
232
+ context 'last day of week of the month:' do
233
+ it 'last day of week 4L' do
234
+ expect(desc('* * * * 4L')).to eq('Jede Minute, am letzten Donnerstag des Monats')
235
+ end
236
+
237
+ it 'last day of week 0L' do
238
+ expect(desc('* * * * 0L')).to eq('Jede Minute, am letzten Sonntag des Monats')
239
+ end
240
+ end
241
+
242
+ it 'last day of the month' do
243
+ expect(desc('*/5 * L JAN *')).to eq('Alle 5 Minuten, am letzten Tag des Monats, nur in Januar')
244
+ end
245
+
246
+ it 'time of day with seconds' do
247
+ expect(desc('30 02 14 * * *')).to eq('Um 2:02:30 PM')
248
+ end
249
+
250
+ it 'second intervals' do
251
+ expect(desc('5-10 * * * * *')).to eq('Sekunden 5 bis 10 vergangene Minute')
252
+ end
253
+
254
+ it 'second minutes hours intervals' do
255
+ expect(desc('5-10 30-35 10-12 * * *')).to eq(
256
+ 'Sekunden 5 bis 10 vergangene Minute, Minuten 30 bis 35 nach der vergangenen Stunde, zwischen 10:00 AM und 12:59 PM')
257
+ end
258
+
259
+ it 'every 5 minutes at 30 seconds' do
260
+ expect(desc('30 */5 * * * *')).to eq('Am 30 Sekunden nach der vergangenen Minute, Alle 5 Minuten')
261
+ end
262
+
263
+ it 'minutes past the hour range' do
264
+ expect(desc('0 30 10-13 ? * WED,FRI')).to eq(
265
+ 'Um 30 Minuten vergangene Stunde, zwischen 10:00 AM und 1:59 PM, nur an Mittwoch und Freitag')
266
+ end
267
+
268
+ it 'seconds past the minute interval' do
269
+ expect(desc('10 0/5 * * * ?')).to eq('Am 10 Sekunden nach der vergangenen Minute, Alle 5 Minuten')
270
+ end
271
+
272
+ it 'between with interval' do
273
+ expect(desc('2-59/3 1,9,22 11-26 1-6 ?')).to eq(
274
+ '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')
275
+ end
276
+
277
+ it 'recurring first of month' do
278
+ expect(desc('0 0 6 1/1 * ?')).to eq('Um 6:00 AM')
279
+ end
280
+
281
+ it 'minutes past the hour' do
282
+ expect(desc('0 5 0/1 * * ?')).to eq('Um 05 Minuten vergangene Stunde')
283
+ end
284
+
285
+ it 'every past the hour' do
286
+ expect(desc('0 0,5,10,15,20,25,30,35,40,45,50,55 * ? * *')).to eq(
287
+ 'Um 00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50 und 55 Minuten vergangene Stunde')
288
+ end
289
+
290
+ it 'every x minute past the hour with interval' do
291
+ expect(desc('0 0-30/2 17 ? * MON-FRI')).to eq(
292
+ 'Alle 2 Minuten, Minuten 00 bis 30 nach der vergangenen Stunde, um 5:00 PM, Montag bis Freitag')
293
+ end
294
+
295
+ it 'one year only with seconds' do
296
+ expect(desc('* * * * * * 2013')).to eq('Jede Sekunde, nur in 2013')
297
+ end
298
+
299
+ it 'one year only without seconds' do
300
+ expect(desc('* * * * * 2013')).to eq('Jede Minute, nur in 2013')
301
+ end
302
+
303
+ it 'two years only' do
304
+ expect(desc('* * * * * 2013,2014')).to eq('Jede Minute, nur in 2013 und 2014')
305
+ end
306
+
307
+ it 'year range 2' do
308
+ expect(desc('23 12 * JAN-FEB * 2013-2014')).to eq('Um 12:23 PM, Januar bis Februar, 2013 bis 2014')
309
+ end
310
+
311
+ it 'year range 3' do
312
+ expect(desc('23 12 * JAN-MAR * 2013-2015')).to eq('Um 12:23 PM, Januar bis März, 2013 bis 2015')
313
+ end
314
+
315
+ context 'multi part range seconds:' do
316
+ it 'multi part range seconds 2,4-5' do
317
+ expect(desc('2,4-5 1 * * *')).to eq('Minuten 02,04 bis 05 nach der vergangenen Stunde, um 1:00 AM')
318
+ end
319
+
320
+ it 'multi part range seconds 2,26-28' do
321
+ expect(desc('2,26-28 18 * * *')).to eq('Minuten 02,26 bis 28 nach der vergangenen Stunde, um 6:00 PM')
322
+ end
323
+ end
324
+
325
+ context 'minutes past the hour:' do
326
+ it 'minutes past the hour 5,10' do
327
+ expect(desc('5,10 0 * * *')).to eq('Um 05 und 10 Minuten vergangene Stunde')
328
+ end
329
+
330
+ it 'minutes past the hour 5,10 day 2' do
331
+ expect(desc('5,10 0 2 * *')).to eq('Um 05 und 10 Minuten vergangene Stunde, am 2 Tag des Monats')
332
+ end
333
+
334
+ it 'minutes past the hour 5/10 day 2' do
335
+ expect(desc('5/10 0 2 * *')).to eq('Alle 10 Minuten, beginnend um 05 Minuten vergangene Stunde, am 2 Tag des Monats')
336
+ end
337
+ end
338
+
339
+ context 'seconds past the minute:' do
340
+ it 'seconds past the minute 5,6' do
341
+ expect(desc('5,6 0 0 * * *')).to eq('Am 5 und 6 Sekunden nach der vergangenen Minute')
342
+ end
343
+
344
+ it 'seconds past the minute 5,6 at 1' do
345
+ expect(desc('5,6 0 1 * * *')).to eq('Am 5 und 6 Sekunden nach der vergangenen Minute, um 1:00 AM')
346
+ end
347
+
348
+ it 'seconds past the minute 5,6 day 2' do
349
+ expect(desc('5,6 0 0 2 * *')).to eq('Am 5 und 6 Sekunden nach der vergangenen Minute, am 2 Tag des Monats')
350
+ end
351
+ end
352
+
353
+ context 'increments starting at X > 1:' do
354
+ it 'second increments' do
355
+ expect(desc('5/15 0 * * * *')).to eq('Alle 15 Sekunden, beginnend am 5 Sekunden nach der vergangenen Minute')
356
+ end
357
+
358
+ it 'minute increments' do
359
+ expect(desc('30/10 * * * *')).to eq('Alle 10 Minuten, beginnend um 30 Minuten vergangene Stunde')
360
+ end
361
+
362
+ it 'hour increments' do
363
+ expect(desc('0 30 2/6 * * ?')).to eq('Um 30 Minuten vergangene Stunde, Alle 6 Stunden, beginnend um 2:00 AM')
364
+ end
365
+
366
+ it 'day of month increments' do
367
+ expect(desc('0 30 8 2/7 * *')).to eq('Um 8:30 AM, Alle 7 Tagen, beginnend am 2 Tag des Monats')
368
+ end
369
+
370
+ it 'day of week increments' do
371
+ expect(desc('0 30 11 * * 2/2')).to eq('Um 11:30 AM, jeden 2 Tag der Woche, beginnend an Dienstag')
372
+ end
373
+
374
+ it 'month increments' do
375
+ expect(desc('0 20 10 * 2/3 THU')).to eq('Um 10:20 AM, nur an Donnerstag, Alle 3 Monaten, beginnend in Februar')
376
+ end
377
+
378
+ it 'year increments' do
379
+ 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')
380
+ end
381
+ end
382
+ end
383
+ end