timely 0.0.2 → 0.1.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 +7 -0
- data/.gitignore +4 -0
- data/.rspec +2 -0
- data/.travis.yml +14 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -12
- data/README.md +5 -0
- data/Rakefile +1 -139
- data/gemfiles/rails3.gemfile +8 -0
- data/gemfiles/rails4.gemfile +9 -0
- data/lib/timely.rb +7 -3
- data/lib/timely/date.rb +20 -0
- data/lib/timely/date_chooser.rb +10 -5
- data/lib/timely/date_range.rb +47 -10
- data/lib/timely/rails.rb +10 -3
- data/lib/timely/rails/calendar_tag.rb +52 -0
- data/lib/timely/rails/date.rb +5 -0
- data/lib/timely/rails/date_group.rb +68 -99
- data/lib/timely/rails/date_range_validity_module.rb +27 -0
- data/lib/timely/rails/date_time.rb +20 -0
- data/lib/timely/rails/extensions.rb +23 -11
- data/lib/timely/rails/period.rb +31 -0
- data/lib/timely/rails/season.rb +65 -75
- data/lib/timely/railtie.rb +7 -0
- data/lib/timely/temporal_patterns/finder.rb +152 -0
- data/lib/timely/temporal_patterns/frequency.rb +108 -0
- data/lib/timely/temporal_patterns/interval.rb +67 -0
- data/lib/timely/temporal_patterns/pattern.rb +160 -0
- data/lib/timely/time_since.rb +17 -0
- data/lib/timely/version.rb +3 -0
- data/spec/calendar_tag_spec.rb +29 -0
- data/spec/date_chooser_spec.rb +36 -27
- data/spec/date_group_spec.rb +9 -9
- data/spec/date_range_spec.rb +58 -20
- data/spec/date_spec.rb +20 -12
- data/spec/extensions_spec.rb +32 -0
- data/spec/rails/date_spec.rb +16 -0
- data/spec/rails/date_time_spec.rb +20 -0
- data/spec/rails/period_spec.rb +17 -0
- data/spec/schema.rb +5 -0
- data/spec/season_spec.rb +21 -24
- data/spec/spec_helper.rb +5 -20
- data/spec/string_spec.rb +4 -3
- data/spec/support/coverage.rb +26 -0
- data/spec/temporal_patterns_spec.rb +28 -0
- data/spec/time_since_spec.rb +24 -0
- data/spec/time_spec.rb +14 -14
- data/spec/trackable_date_set_spec.rb +14 -14
- data/spec/week_days_spec.rb +18 -18
- data/timely.gemspec +34 -98
- metadata +244 -21
- data/lib/timely/temporal_patterns.rb +0 -441
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2cebe03ec2467f4efe23f881f70be2c08fbb7e20
|
4
|
+
data.tar.gz: 355bf2273646023df6e0f7e9218e7a91390dd25a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bec47226548cc65af0aa7e0da099b5dc4f4b80056eb1f47e0f5de53959db654b18ed851245fbab86f9d45a0d80cb3fcc3a0bbcc9cc6188958d120402832b78f1
|
7
|
+
data.tar.gz: c705e73fe8447761b8ea7a79984a77aeb13687bb81bc354e53f5f434d64f9d70f51325da10f81df7811e3c02a18621e02cc5b6dbcf7defcb33aa6f944ea066fe
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 2.2
|
4
|
+
script: bundle exec rake spec
|
5
|
+
gemfile:
|
6
|
+
- gemfiles/rails3.gemfile
|
7
|
+
- gemfiles/rails4.gemfile
|
8
|
+
notifications:
|
9
|
+
email:
|
10
|
+
- support@travellink.com.au
|
11
|
+
flowdock:
|
12
|
+
secure: QC1mV/0NZwA4tU2K1BQSety/seEf7ujL3uUlddXrMm0yHp0NBMlo1tnQ7KKopSKoyoPj9M9KmfhrCdbdZXDOU57WucH+pz7Tn9Zp9VkPUMniN4rYSwkrF17vihM5NpdyDzqo5mzthVPUEV0DtlK+Uu2W4wMUpu1uKaahFzHJH6k=
|
13
|
+
sudo: false
|
14
|
+
cache: bundler
|
data/Gemfile
CHANGED
@@ -1,13 +1,2 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
gemspec
|
3
|
-
|
4
|
-
group :development, :test do
|
5
|
-
gem 'rake', '~> 0.9.2'
|
6
|
-
gem 'rdoc', '~> 3.12'
|
7
|
-
gem 'rspec'
|
8
|
-
gem 'simplecov-rcov'
|
9
|
-
gem 'simplecov'
|
10
|
-
gem 'sqlite3'
|
11
|
-
gem 'activesupport', '~> 2.3.0'
|
12
|
-
gem 'activerecord', '~> 2.3.0'
|
13
|
-
end
|
data/README.md
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
Timely
|
2
2
|
======
|
3
3
|
|
4
|
+
[](https://travis-ci.org/sealink/timely)
|
5
|
+
[](https://coveralls.io/r/sealink/timely)
|
6
|
+
[](https://gemnasium.com/sealink/timely)
|
7
|
+
[](https://codeclimate.com/github/sealink/timely)
|
8
|
+
|
4
9
|
# DESCRIPTION
|
5
10
|
|
6
11
|
Various helpers to work with times, dates and weekdays, etc.
|
data/Rakefile
CHANGED
@@ -1,47 +1,4 @@
|
|
1
|
-
require
|
2
|
-
require 'rake'
|
3
|
-
require 'date'
|
4
|
-
|
5
|
-
#############################################################################
|
6
|
-
#
|
7
|
-
# Helper functions
|
8
|
-
#
|
9
|
-
#############################################################################
|
10
|
-
|
11
|
-
def name
|
12
|
-
@name ||= Dir['*.gemspec'].first.split('.').first
|
13
|
-
end
|
14
|
-
|
15
|
-
def version
|
16
|
-
line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
|
17
|
-
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
18
|
-
end
|
19
|
-
|
20
|
-
def date
|
21
|
-
Date.today.to_s
|
22
|
-
end
|
23
|
-
|
24
|
-
def rubyforge_project
|
25
|
-
name
|
26
|
-
end
|
27
|
-
|
28
|
-
def gemspec_file
|
29
|
-
"#{name}.gemspec"
|
30
|
-
end
|
31
|
-
|
32
|
-
def gem_file
|
33
|
-
"#{name}-#{version}.gem"
|
34
|
-
end
|
35
|
-
|
36
|
-
def replace_header(head, header_name)
|
37
|
-
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
|
38
|
-
end
|
39
|
-
|
40
|
-
#############################################################################
|
41
|
-
#
|
42
|
-
# Standard tasks
|
43
|
-
#
|
44
|
-
#############################################################################
|
1
|
+
require "bundler/gem_tasks"
|
45
2
|
|
46
3
|
desc 'Default: run specs.'
|
47
4
|
task :default => :spec
|
@@ -53,98 +10,3 @@ RSpec::Core::RakeTask.new do |t|
|
|
53
10
|
t.pattern = "./spec/**/*_spec.rb" # don't need this, it's default.
|
54
11
|
# Put spec opts in a file named .rspec in root
|
55
12
|
end
|
56
|
-
|
57
|
-
desc "Generate SimpleCov test coverage and open in your browser"
|
58
|
-
task :coverage do
|
59
|
-
ENV['COVERAGE'] = 'true'
|
60
|
-
Rake::Task['spec'].invoke
|
61
|
-
end
|
62
|
-
|
63
|
-
require 'rdoc/task'
|
64
|
-
RDoc::Task.new do |rdoc|
|
65
|
-
rdoc.rdoc_dir = 'rdoc'
|
66
|
-
rdoc.title = "#{name} #{version}"
|
67
|
-
rdoc.rdoc_files.include('README*')
|
68
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
69
|
-
end
|
70
|
-
|
71
|
-
desc "Open an irb session preloaded with this library"
|
72
|
-
task :console do
|
73
|
-
sh "irb -rubygems -r ./lib/#{name}.rb"
|
74
|
-
end
|
75
|
-
|
76
|
-
#############################################################################
|
77
|
-
#
|
78
|
-
# Custom tasks (add your own tasks here)
|
79
|
-
#
|
80
|
-
#############################################################################
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
#############################################################################
|
85
|
-
#
|
86
|
-
# Packaging tasks
|
87
|
-
#
|
88
|
-
#############################################################################
|
89
|
-
|
90
|
-
desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
|
91
|
-
task :release => :build do
|
92
|
-
unless `git branch` =~ /^\* master$/
|
93
|
-
puts "You must be on the master branch to release!"
|
94
|
-
exit!
|
95
|
-
end
|
96
|
-
sh "git commit --allow-empty -a -m 'Release #{version}'"
|
97
|
-
sh "git tag v#{version}"
|
98
|
-
sh "git push origin master"
|
99
|
-
sh "git push origin v#{version}"
|
100
|
-
sh "gem push pkg/#{name}-#{version}.gem"
|
101
|
-
end
|
102
|
-
|
103
|
-
desc "Build #{gem_file} into the pkg directory"
|
104
|
-
task :build => :gemspec do
|
105
|
-
sh "mkdir -p pkg"
|
106
|
-
sh "gem build #{gemspec_file}"
|
107
|
-
sh "mv #{gem_file} pkg"
|
108
|
-
end
|
109
|
-
|
110
|
-
desc "Generate #{gemspec_file}"
|
111
|
-
task :gemspec => :validate do
|
112
|
-
# read spec file and split out manifest section
|
113
|
-
spec = File.read(gemspec_file)
|
114
|
-
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
115
|
-
|
116
|
-
# replace name version and date
|
117
|
-
replace_header(head, :name)
|
118
|
-
replace_header(head, :version)
|
119
|
-
replace_header(head, :date)
|
120
|
-
#comment this out if your rubyforge_project has a different name
|
121
|
-
replace_header(head, :rubyforge_project)
|
122
|
-
|
123
|
-
# determine file list from git ls-files
|
124
|
-
files = `git ls-files`.
|
125
|
-
split("\n").
|
126
|
-
sort.
|
127
|
-
reject { |file| file =~ /^\./ }.
|
128
|
-
reject { |file| file =~ /^(rdoc|pkg)/ }.
|
129
|
-
map { |file| " #{file}" }.
|
130
|
-
join("\n")
|
131
|
-
|
132
|
-
# piece file back together and write
|
133
|
-
manifest = " s.files = %w[\n#{files}\n ]\n"
|
134
|
-
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
|
135
|
-
File.open(gemspec_file, 'w') { |io| io.write(spec) }
|
136
|
-
puts "Updated #{gemspec_file}"
|
137
|
-
end
|
138
|
-
|
139
|
-
desc "Validate #{gemspec_file}"
|
140
|
-
task :validate do
|
141
|
-
libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
|
142
|
-
unless libfiles.empty?
|
143
|
-
puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
|
144
|
-
exit!
|
145
|
-
end
|
146
|
-
unless Dir['VERSION*'].empty?
|
147
|
-
puts "A `VERSION` file at root level violates Gem best practices."
|
148
|
-
exit!
|
149
|
-
end
|
150
|
-
end
|
data/lib/timely.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
module Timely
|
2
|
-
VERSION = '0.0.2'
|
3
|
-
|
4
2
|
require 'time'
|
5
3
|
require 'date'
|
6
4
|
|
7
5
|
require 'timely/string'
|
8
6
|
require 'timely/date'
|
9
7
|
require 'timely/time'
|
8
|
+
require 'timely/time_since'
|
10
9
|
require 'timely/date_time'
|
11
10
|
require 'timely/range'
|
12
11
|
require 'timely/date_range'
|
13
12
|
require 'timely/date_chooser'
|
14
13
|
require 'timely/week_days'
|
15
|
-
require 'timely/temporal_patterns'
|
14
|
+
require 'timely/temporal_patterns/finder'
|
15
|
+
require 'timely/temporal_patterns/frequency'
|
16
|
+
require 'timely/temporal_patterns/interval'
|
17
|
+
require 'timely/temporal_patterns/pattern'
|
16
18
|
require 'timely/trackable_date_set'
|
19
|
+
|
20
|
+
require 'timely/railtie' if defined?(Rails::Railtie)
|
17
21
|
end
|
data/lib/timely/date.rb
CHANGED
@@ -10,6 +10,26 @@ module Timely
|
|
10
10
|
end
|
11
11
|
|
12
12
|
alias_method :at, :at_time
|
13
|
+
|
14
|
+
# returns true if date between from and to
|
15
|
+
# however if from and/or to are nil, it ignores that query
|
16
|
+
# e.g. date.between?(from, nil) is "date > from",
|
17
|
+
# date.between?(from, nil) is "date < to"
|
18
|
+
# date.between?(nil, nil) is true
|
19
|
+
def between?(from, to)
|
20
|
+
from = from.to_date if from && !from.is_a?(Date)
|
21
|
+
to = to.to_date if to && !to.is_a?(Date)
|
22
|
+
|
23
|
+
if from && to
|
24
|
+
self >= from && self <= to
|
25
|
+
elsif from
|
26
|
+
self >= from
|
27
|
+
elsif to
|
28
|
+
self <= to
|
29
|
+
else
|
30
|
+
true # i.e. no restrictive range return true
|
31
|
+
end
|
32
|
+
end
|
13
33
|
end
|
14
34
|
end
|
15
35
|
|
data/lib/timely/date_chooser.rb
CHANGED
@@ -3,9 +3,9 @@ module Timely
|
|
3
3
|
# Where is this used... so far only in one place, _date_range.html.haml
|
4
4
|
# May be good to refactor this as well, after the class behaviour is refactored.
|
5
5
|
INTERVALS = [
|
6
|
-
{:code => '
|
6
|
+
{:code => 'week', :name => 'week(s)', :description =>
|
7
7
|
'Weekdays selected will be chosen every {{n}} weeks for the date range'},
|
8
|
-
{:code => '
|
8
|
+
{:code => 'week_of_month', :name => 'week of month', :description =>
|
9
9
|
'Weekdays selected will be chosen in their {{ord}} occurance every month,
|
10
10
|
e.g. if wednesday and thursday are selected, the first wednesday and
|
11
11
|
first thursday are selected. Note: this may mean the booking is copied
|
@@ -20,6 +20,7 @@ module Timely
|
|
20
20
|
@to = process_date(options[:to])
|
21
21
|
@select = options[:select]
|
22
22
|
@dates = options[:dates]
|
23
|
+
@specific_dates = options[:specific_dates]
|
23
24
|
@interval = options[:interval]
|
24
25
|
@weekdays = WeekDays.new(options[:weekdays]) if @select == 'weekdays'
|
25
26
|
validate
|
@@ -40,7 +41,8 @@ module Timely
|
|
40
41
|
# :to - The end of the date range
|
41
42
|
#
|
42
43
|
# You can either specify specific dates to be chosen each month:
|
43
|
-
# :dates
|
44
|
+
# :dates - A comma separated string of days of the month, e.g. 1,16
|
45
|
+
# :specific_dates - A comma separated string of dates, e.g. 26-10-2012, 03-11-2012, 01-01-2013
|
44
46
|
#
|
45
47
|
# or you can specify how to select the dates
|
46
48
|
# :day - A hash of days, the index being the wday, e.g. 0 = sunday, and the value being 1 if chosen
|
@@ -60,6 +62,9 @@ module Timely
|
|
60
62
|
when 'days'
|
61
63
|
days = @dates.gsub(/\s/, '').split(',')
|
62
64
|
all_days.select { |date| days.include?(date.mday.to_s) }
|
65
|
+
when 'specific_days'
|
66
|
+
days = @specific_dates.gsub(/\s/, '').split(',')
|
67
|
+
days.map(&:to_date)
|
63
68
|
when 'weekdays'
|
64
69
|
raise DateChooserException, "No days of the week selected" if @weekdays.weekdays.empty?
|
65
70
|
raise DateChooserException, "No weekly interval selected" if @interval && @interval.empty?
|
@@ -67,12 +72,12 @@ module Timely
|
|
67
72
|
all_days.select do |date|
|
68
73
|
if @weekdays.has_day?(date.wday)
|
69
74
|
case @interval[:unit]
|
70
|
-
when '
|
75
|
+
when 'week'
|
71
76
|
# 0 = first week, 1 = second week, 2 = third week, etc.
|
72
77
|
nth_week = (date - @from).to_i / 7
|
73
78
|
# true every 2nd week (0, 2, 4, 6, etc.)
|
74
79
|
(nth_week % @interval[:level].to_i).zero?
|
75
|
-
when '
|
80
|
+
when 'week_of_month'
|
76
81
|
week = @interval[:level].to_i
|
77
82
|
(date.mday > (week-1)*7 && date.mday <= week*7)
|
78
83
|
end
|
data/lib/timely/date_range.rb
CHANGED
@@ -1,17 +1,30 @@
|
|
1
|
+
require 'date' # Ensure Date class is loaded for old rubies (1.8)
|
2
|
+
|
1
3
|
module Timely
|
2
4
|
class DateRange < ::Range
|
3
5
|
def initialize(*args)
|
4
6
|
if args.first.is_a?(Range)
|
5
|
-
|
7
|
+
date_range = args.first
|
8
|
+
DateRange.validate_range(date_range.first, date_range.last)
|
9
|
+
super(date_range.first.to_date, date_range.last.to_date)
|
6
10
|
elsif args.size == 1 && args.first.is_a?(Date)
|
7
|
-
|
11
|
+
DateRange.validate_range(args.first, args.last)
|
12
|
+
super(args.first.to_date, args.first.to_date)
|
8
13
|
else
|
9
|
-
|
14
|
+
DateRange.validate_range(args.first, args.last)
|
15
|
+
super(args.first.to_date, args.last.to_date)
|
10
16
|
end
|
11
17
|
end
|
12
18
|
alias_method :start_date, :first
|
13
19
|
alias_method :end_date, :last
|
14
20
|
|
21
|
+
def self.validate_range(first, last)
|
22
|
+
raise ArgumentError, "Date range missing start date" if first.nil?
|
23
|
+
raise ArgumentError, "Date range missing end date" if last.nil?
|
24
|
+
raise ArgumentError, "Start date is not a date" unless first.is_a? Date
|
25
|
+
raise ArgumentError, "End date is not a date" unless last.is_a? Date
|
26
|
+
end
|
27
|
+
|
15
28
|
def self.from_params(start_date, duration = nil)
|
16
29
|
start_date = start_date.to_date
|
17
30
|
duration = [1, duration.to_i].max
|
@@ -34,18 +47,42 @@ module Timely
|
|
34
47
|
end
|
35
48
|
alias_method :duration, :number_of_nights
|
36
49
|
|
37
|
-
def to_s(fmt = '%b %Y')
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
50
|
+
def to_s(fmt = '%b %Y', date_fmt = '%Y-%m-%d')
|
51
|
+
Timely::DateRange.to_s(first, last, fmt, date_fmt)
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.to_s(first = nil, last = nil, month_fmt = '%b %Y', date_fmt = default_date_format, time_fmt = nil)
|
55
|
+
time_fmt ||= date_fmt + ' %H:%M'
|
56
|
+
is_date = first.is_a?(Date) || last.is_a?(Date)
|
57
|
+
fmt = is_date ? date_fmt : time_fmt
|
58
|
+
if first && last
|
59
|
+
if first == last
|
42
60
|
first.strftime(fmt)
|
61
|
+
elsif first == first.at_beginning_of_month && last == last.at_end_of_month
|
62
|
+
if first.month == last.month
|
63
|
+
first.strftime(month_fmt)
|
64
|
+
else
|
65
|
+
"#{first.strftime(month_fmt)} to #{last.strftime(month_fmt)}"
|
66
|
+
end
|
43
67
|
else
|
44
|
-
"#{first.strftime(fmt)} to #{last.strftime(fmt)}"
|
68
|
+
"#{first.strftime(fmt)} to #{last.strftime(fmt)}#{" (inclusive)" if is_date}"
|
45
69
|
end
|
70
|
+
elsif first
|
71
|
+
"on or after #{first.strftime(fmt)}"
|
72
|
+
elsif last
|
73
|
+
"on or before #{last.strftime(fmt)}"
|
46
74
|
else
|
47
|
-
"
|
75
|
+
"no date range"
|
48
76
|
end
|
49
77
|
end
|
78
|
+
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def self.default_date_format
|
83
|
+
# ::Date as we want Ruby's Date not Timely::Date
|
84
|
+
date_format = ::Date::DATE_FORMATS[:short] if ::Date.const_defined?('DATE_FORMATS')
|
85
|
+
date_format || '%Y-%m-%d'
|
86
|
+
end
|
50
87
|
end
|
51
88
|
end
|
data/lib/timely/rails.rb
CHANGED
@@ -1,4 +1,11 @@
|
|
1
1
|
require 'timely/rails/extensions'
|
2
|
-
ActiveRecord
|
3
|
-
|
4
|
-
require 'timely/rails/
|
2
|
+
if defined?(ActiveRecord)
|
3
|
+
ActiveRecord::Base.extend Timely::Extensions
|
4
|
+
require 'timely/rails/season'
|
5
|
+
require 'timely/rails/date_group'
|
6
|
+
end
|
7
|
+
require 'timely/rails/date_range_validity_module'
|
8
|
+
require 'timely/rails/calendar_tag'
|
9
|
+
require 'timely/rails/date_time'
|
10
|
+
require 'timely/rails/date'
|
11
|
+
require 'timely/rails/period'
|