cronex 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YzZlZDk0MGYzNDdhZDY2MGVkZGUwMDI3NDhiZjYxNDRhMjhkMjQ0ZA==
5
+ data.tar.gz: !binary |-
6
+ YzU5N2E3ZDI5NGQzMGY4NmMyN2Q1OTIwYTQwMWExZjc2YjUyOWE3YQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MDhhMzZjMTczNDhkMjYwZjNiYmZlNDMxYTE1YThkZGYzNmNmYTA2MGQwYzQ4
10
+ YTY2NWRiMTk0NjYzNmQ5MzBhYTVhZTZlZDkxM2Y3MzQ3MjBkNmQxZTYwY2Yx
11
+ ZDk3NTEzNzgxMjUxZDdmOWRkMjVmYWE3NzM0OGYzOTgzMTQwYjQ=
12
+ data.tar.gz: !binary |-
13
+ MjZlNTcwYWJmM2Y0OGI1MzE1NjdiMDQzMzk5NjYxNmFiYzY1YTgxYTk1ZDAw
14
+ YjdhNDQ0Njc2ODE0NjE4ZmY1OTJhYTgyYWVhYjcyN2JlZjViYTE5ZmY5YWVi
15
+ OGRlYjJkOWEwNTFlZTU5ZDNmNGNlZTZkMzkyOWE3MDkzYzU2YzY=
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.log
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .rvmrc
7
+ .yardoc
8
+ Gemfile.lock
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ temp
19
+ tmp
20
+ vendor
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,47 @@
1
+ Encoding:
2
+ Enabled: false
3
+
4
+ AmbiguousOperator:
5
+ Enabled: false
6
+
7
+ CaseIndentation:
8
+ Enabled: false
9
+
10
+ CyclomaticComplexity:
11
+ Enabled: false
12
+ Max: 10
13
+
14
+ PerceivedComplexity:
15
+ Enabled: false
16
+ Max: 10
17
+
18
+ Documentation:
19
+ Enabled: false
20
+
21
+ EmptyLinesAroundBody:
22
+ Enabled: false
23
+
24
+ ClassLength:
25
+ Enabled: false
26
+
27
+ LineLength:
28
+ Enabled: true
29
+ Max: 160
30
+
31
+ MethodLength:
32
+ Enabled: false
33
+
34
+ ModuleFunction:
35
+ Enabled: false
36
+
37
+ NestedTernaryOperator:
38
+ Enabled: false
39
+
40
+ RaiseArgs:
41
+ Enabled: false
42
+
43
+ RescueModifier:
44
+ Enabled: false
45
+
46
+ UnusedMethodArgument:
47
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,2 @@
1
+ ### [0.2.0] - 2015-10-25
2
+ - Initial public version
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE.md ADDED
@@ -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.
data/README.md ADDED
@@ -0,0 +1,56 @@
1
+ #Cronex
2
+
3
+ A Ruby library that converts cron expressions into human readable strings.
4
+ Translated to Ruby from [cron-expression-descriptor](https://github.com/bradyholt/cron-expression-descriptor) (C#) via
5
+ [cron-parser](https://github.com/RedHogs/cron-parser) (Java).
6
+
7
+ Original Author & Credit: Brady Holt (http://www.geekytidbits.com).
8
+
9
+ ## Features
10
+
11
+ * Supports all cron expression special characters including: `*` `/` `,` `-` `?` `L` `W` `#`
12
+ * Supports 5, 6 (w/ seconds or year), or 7 (w/ seconds and year) part cron expressions
13
+ * Provides casing options (sentence, title, lower)
14
+ * Support for non-standard non-zero-based week day numbers
15
+ * Supports printing to locale specific human readable format
16
+
17
+ For a quick intro to cron see Quartz [Cron Tutorial](http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger).
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ gem 'cronex'
24
+
25
+ And then execute:
26
+
27
+ $ bundle install
28
+
29
+ Or install it yourself as:
30
+
31
+ $ gem install cronex
32
+
33
+ ## Usage
34
+
35
+ #### Zero based day of week
36
+
37
+ Cronex::ExpressionDescriptor.new('*/5 15 * * 1-5').description
38
+ => Every 5 minutes, at 3:00 PM, Monday through Friday
39
+
40
+ Cronex::ExpressionDescriptor.new('0 0/30 8-9 5,20 * ?').description
41
+ => Every 30 minutes, between 8:00 AM and 9:59 AM, on day 5 and 20 of the month
42
+
43
+ #### Non-zero based day of week
44
+
45
+ Cronex::ExpressionDescriptor.new('*/5 15 * * 1-5', zero_based_dow: false).description
46
+ => Every 5 minutes, at 3:00 PM, Sunday through Thursday
47
+
48
+ See spec tests for more examples.
49
+
50
+ ### Contributing
51
+
52
+ 1. Fork it
53
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
54
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
55
+ 4. Push to the branch (`git push origin my-new-feature`)
56
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new do |t|
5
+ t.pattern = 'spec/*_spec.rb'
6
+ end
7
+
8
+ task :default => :spec
data/cronex.gemspec ADDED
@@ -0,0 +1,26 @@
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'
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_development_dependency 'pry', '~> 0.10'
24
+ spec.add_development_dependency 'rake', '~> 10.1'
25
+ spec.add_development_dependency 'rspec', '~> 3.1'
26
+ end
data/lib/cronex.rb ADDED
@@ -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'
@@ -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'
@@ -0,0 +1,59 @@
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_description)
16
+ if expression.empty? || expression == '0'
17
+ desc = ''
18
+ elsif expression == '*'
19
+ desc = all_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
+ desc += ', ' + 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
+ elsif !Cronex::Utils.include_any?(segments[0], special_chars + ['*'])
34
+ desc += ', ' + format(starting_description_format(segments[0]), single_item_description(segments[0]))
35
+ end
36
+ elsif expression.include?('-')
37
+ segments = expression.split('-')
38
+ desc = format(
39
+ between_description_format(expression),
40
+ single_item_description(segments[0]),
41
+ single_item_description(segments[1]).gsub(':00', ':59'))
42
+ elsif expression.include?(',')
43
+ segments = expression.split(',')
44
+ segments = segments.map { |s| single_item_description(s) }
45
+ desc_content = segments[0...-1].join(', ') + ' ' + resources.get('and') + ' ' + segments.last
46
+ desc = format(description_format(expression), desc_content)
47
+ end
48
+
49
+ desc
50
+ end
51
+
52
+ def plural(expression, singular, plural)
53
+ number = Cronex::Utils.number?(expression)
54
+ return plural if number && number > 1
55
+ return plural if expression.include?(',')
56
+ singular
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,23 @@
1
+ module Cronex
2
+ class DayOfMonthDescription < Description
3
+ def single_item_description(expression)
4
+ 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
@@ -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 = 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 Cronex::Utils.day_of_week_name(0) # or 7 as in java DateTime().withDayOfWeek(7) for Sunday
17
+ elsif !zero_based_dow
18
+ dow_num -= 1
19
+ end
20
+ return Cronex::Utils.day_of_week_name(dow_num)
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 forth 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
@@ -0,0 +1,23 @@
1
+ module Cronex
2
+ class HoursDescription < Description
3
+ def single_item_description(expression)
4
+ Cronex::Utils.format_time(expression, '0')
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
@@ -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
@@ -0,0 +1,23 @@
1
+ module Cronex
2
+ class MonthDescription < Description
3
+ def single_item_description(expression)
4
+ DateTime.new(Time.now.year, Integer(expression), 1).strftime('%B')
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