cronex 0.7.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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