timely 0.4.2 → 0.9.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 +4 -4
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/release.yml +59 -0
- data/.github/workflows/ruby.yml +19 -0
- data/.rubocop.yml +22 -2
- data/.ruby-version +1 -1
- data/CHANGELOG.md +23 -0
- data/Gemfile +2 -0
- data/README.md +13 -2
- data/Rakefile +6 -4
- data/gemfiles/rails60.gemfile +8 -0
- data/gemfiles/rails61.gemfile +8 -0
- data/lib/timely.rb +2 -0
- data/lib/timely/date.rb +6 -2
- data/lib/timely/date_chooser.rb +29 -30
- data/lib/timely/date_range.rb +17 -19
- data/lib/timely/date_time.rb +3 -1
- data/lib/timely/rails.rb +2 -0
- data/lib/timely/rails/calendar_tag.rb +3 -3
- data/lib/timely/rails/date.rb +3 -1
- data/lib/timely/rails/date_group.rb +42 -18
- data/lib/timely/rails/date_range_validity_module.rb +8 -6
- data/lib/timely/rails/date_time.rb +5 -3
- data/lib/timely/rails/extensions.rb +12 -37
- data/lib/timely/rails/period.rb +14 -12
- data/lib/timely/rails/season.rb +14 -33
- data/lib/timely/rails/time.rb +7 -3
- data/lib/timely/railtie.rb +2 -0
- data/lib/timely/range.rb +4 -2
- data/lib/timely/string.rb +4 -2
- data/lib/timely/time.rb +7 -3
- data/lib/timely/time_since.rb +5 -3
- data/lib/timely/trackable_date_set.rb +21 -21
- data/lib/timely/version.rb +3 -1
- data/lib/timely/week_days.rb +22 -14
- data/rails/init.rb +2 -0
- data/spec/calendar_tag_spec.rb +11 -10
- data/spec/date_chooser_spec.rb +67 -62
- data/spec/date_group_spec.rb +103 -5
- data/spec/date_range_spec.rb +29 -19
- data/spec/date_spec.rb +3 -1
- data/spec/extensions_spec.rb +5 -9
- data/spec/rails/date_spec.rb +5 -3
- data/spec/rails/date_time_spec.rb +9 -7
- data/spec/rails/period_spec.rb +2 -0
- data/spec/rails/time_spec.rb +6 -4
- data/spec/schema.rb +4 -3
- data/spec/season_spec.rb +23 -26
- data/spec/spec_helper.rb +16 -1
- data/spec/support/coverage_loader.rb +3 -1
- data/spec/temporal_patterns_spec.rb +5 -5
- data/spec/time_since_spec.rb +6 -4
- data/spec/time_spec.rb +6 -4
- data/spec/trackable_date_set_spec.rb +20 -18
- data/spec/week_days_spec.rb +41 -16
- data/timely.gemspec +23 -19
- metadata +54 -26
- data/.travis.yml +0 -22
- data/gemfiles/rails5.gemfile +0 -6
- data/gemfiles/rails6.gemfile +0 -6
- data/spec/string_spec.rb +0 -14
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5aeec444ee90189672055555263e90807c7f2bad4e366c5e44d74dd4d578cd30
|
|
4
|
+
data.tar.gz: e5bf46db86fee6448233e03aaba2dfe7dc7f66771f6d82c30db2e231e03b48b9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a47c451934a28dda82fae5eb78145791b5d8727e371683f506ade5f3ee4f609167bf5bec209c1dd545ae8399fa82df22ec994903df4c000c36b844b8c42255f3
|
|
7
|
+
data.tar.gz: bc96a85cae09b52d5381a915847c1f76df9613592e632403ca1d69dca74486f7d7bf464b5777d850bb88689cba0ded45101c49503470f2c0e8242d3f09a1f420
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
name: Build
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout
|
|
14
|
+
uses: actions/checkout@v2
|
|
15
|
+
- uses: ruby/setup-ruby@v1
|
|
16
|
+
with:
|
|
17
|
+
bundler-cache: true
|
|
18
|
+
- run: bundle exec rake
|
|
19
|
+
|
|
20
|
+
release:
|
|
21
|
+
needs: build
|
|
22
|
+
name: Release
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- name: Checkout
|
|
26
|
+
uses: actions/checkout@v2
|
|
27
|
+
|
|
28
|
+
- name: Generate Changelog
|
|
29
|
+
run: |
|
|
30
|
+
# Get version from github ref (remove 'refs/tags/' and prefix 'v')
|
|
31
|
+
version="${GITHUB_REF#refs/tags/v}"
|
|
32
|
+
npx changelog-parser CHANGELOG.md | jq -cr ".versions | .[] | select(.version == \"$version\") | .body" > ${{ github.workflow }}-CHANGELOG.txt
|
|
33
|
+
|
|
34
|
+
- name: Release
|
|
35
|
+
uses: softprops/action-gh-release@v1
|
|
36
|
+
with:
|
|
37
|
+
body_path: ${{ github.workflow }}-CHANGELOG.txt
|
|
38
|
+
env:
|
|
39
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
40
|
+
|
|
41
|
+
publish:
|
|
42
|
+
needs: [build, release]
|
|
43
|
+
name: Publish
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v2
|
|
48
|
+
- uses: ruby/setup-ruby@v1
|
|
49
|
+
|
|
50
|
+
- name: Publish to RubyGems
|
|
51
|
+
run: |
|
|
52
|
+
mkdir -p $HOME/.gem
|
|
53
|
+
touch $HOME/.gem/credentials
|
|
54
|
+
chmod 0600 $HOME/.gem/credentials
|
|
55
|
+
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
|
56
|
+
gem build *.gemspec
|
|
57
|
+
gem push *.gem
|
|
58
|
+
env:
|
|
59
|
+
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: Build and Test
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
jobs:
|
|
4
|
+
test:
|
|
5
|
+
strategy:
|
|
6
|
+
fail-fast: false
|
|
7
|
+
matrix:
|
|
8
|
+
gemfile: [rails60, rails61]
|
|
9
|
+
ruby: ["2.6", "2.7", "3.0"]
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
env:
|
|
12
|
+
BUNDLE_GEMFILE: gemfiles/${{ matrix.gemfile }}.gemfile
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v2
|
|
15
|
+
- uses: ruby/setup-ruby@v1
|
|
16
|
+
with:
|
|
17
|
+
ruby-version: ${{ matrix.ruby }}
|
|
18
|
+
bundler-cache: true
|
|
19
|
+
- run: bundle exec rake
|
data/.rubocop.yml
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 2.6
|
|
3
|
+
Exclude:
|
|
4
|
+
- lib/timely/temporal_patterns/*.rb
|
|
5
|
+
|
|
1
6
|
Metrics/LineLength:
|
|
2
|
-
Max:
|
|
7
|
+
Max: 200
|
|
3
8
|
|
|
4
9
|
Style/Documentation:
|
|
5
10
|
Enabled: false
|
|
6
11
|
|
|
7
12
|
Style/FrozenStringLiteralComment:
|
|
8
|
-
Enabled:
|
|
13
|
+
Enabled: true
|
|
14
|
+
|
|
15
|
+
Metrics/BlockLength:
|
|
16
|
+
Enabled: false
|
|
17
|
+
|
|
18
|
+
Metrics/MethodLength:
|
|
19
|
+
Enabled: false
|
|
20
|
+
|
|
21
|
+
Metrics/AbcSize:
|
|
22
|
+
Enabled: false
|
|
23
|
+
|
|
24
|
+
Metrics/CyclomaticComplexity:
|
|
25
|
+
Enabled: false
|
|
26
|
+
|
|
27
|
+
Metrics/PerceivedComplexity:
|
|
28
|
+
Enabled: false
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
3.0.0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.0
|
|
4
|
+
|
|
5
|
+
* [TT-8614] Update to build with github actions / ruby 3.0 / rails 6.1
|
|
6
|
+
|
|
7
|
+
## 0.8.0
|
|
8
|
+
|
|
9
|
+
* [TT-6441] Turns out we don't actually need time difference in QT
|
|
10
|
+
* [TT-6661] Fix issue when detecting intersecting date groups
|
|
11
|
+
|
|
12
|
+
## 0.7.0
|
|
13
|
+
|
|
14
|
+
* [TT-6441] Due to TimeDifference being unmaintained bring it into the timely library
|
|
15
|
+
|
|
16
|
+
## 0.6.0
|
|
17
|
+
|
|
18
|
+
* [TT-6402] Require date group weekdays bit field to be not null/nil
|
|
19
|
+
IMPORTANT: Rails projects must add a migration to make this field not null!
|
|
20
|
+
* [TT-6401] Remove Rails 3 support, unused methods
|
|
21
|
+
|
|
22
|
+
## 0.5.0
|
|
23
|
+
|
|
24
|
+
* [TT-6193] Date group scopes for more efficient searches/restrictions
|
|
25
|
+
|
|
3
26
|
## 0.4.2
|
|
4
27
|
|
|
5
28
|
* [TT-5794] Fix belongs_to associations are not explicitly marked optional
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# Timely
|
|
2
2
|
|
|
3
|
-
[](https://github.com/sealink/timely/actions)
|
|
4
4
|
[](https://coveralls.io/r/sealink/timely)
|
|
5
|
-
[](https://gemnasium.com/sealink/timely)
|
|
6
5
|
[](https://codeclimate.com/github/sealink/timely)
|
|
7
6
|
|
|
8
7
|
# DESCRIPTION
|
|
@@ -59,3 +58,15 @@ some_date.at_time(some_time) # => Sat May 03 13:40:22 -0500 2008
|
|
|
59
58
|
some_time.on(some_date) # => Sat May 03 13:40:22 -0500 2008
|
|
60
59
|
some_date.at(some_time) # => Sat May 03 13:40:22 -0500 2008
|
|
61
60
|
```
|
|
61
|
+
|
|
62
|
+
# Release
|
|
63
|
+
|
|
64
|
+
To publish a new version of this gem the following steps must be taken.
|
|
65
|
+
|
|
66
|
+
* Update the version in the following files
|
|
67
|
+
```
|
|
68
|
+
CHANGELOG.md
|
|
69
|
+
lib/timely/version.rb
|
|
70
|
+
````
|
|
71
|
+
* Create a tag using the format v0.1.0
|
|
72
|
+
* Follow build progress in GitHub actions
|
data/Rakefile
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
2
4
|
|
|
3
5
|
desc 'Default: run specs.'
|
|
4
|
-
task :
|
|
6
|
+
task default: :spec
|
|
5
7
|
|
|
6
8
|
require 'rspec/core/rake_task'
|
|
7
9
|
|
|
8
|
-
desc
|
|
10
|
+
desc 'Run specs'
|
|
9
11
|
RSpec::Core::RakeTask.new do |t|
|
|
10
|
-
t.pattern =
|
|
12
|
+
t.pattern = './spec/**/*_spec.rb' # don't need this, it's default.
|
|
11
13
|
# Put spec opts in a file named .rspec in root
|
|
12
14
|
end
|
data/lib/timely.rb
CHANGED
data/lib/timely/date.rb
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Timely
|
|
2
4
|
module Date
|
|
3
5
|
def at_time(hour = nil, minute = nil, second = nil)
|
|
4
6
|
if hour.is_a?(::Time)
|
|
5
7
|
time = hour
|
|
6
|
-
hour
|
|
8
|
+
hour = time.hour
|
|
9
|
+
minute = time.min
|
|
10
|
+
second = time.sec
|
|
7
11
|
end
|
|
8
12
|
|
|
9
13
|
::Time.local(year, month, day, hour, minute, second)
|
|
10
14
|
end
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
alias at at_time
|
|
13
17
|
|
|
14
18
|
# returns true if date between from and to
|
|
15
19
|
# however if from and/or to are nil, it ignores that query
|
data/lib/timely/date_chooser.rb
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Timely
|
|
2
4
|
class DateChooser
|
|
3
5
|
# Where is this used... so far only in one place, _date_range.html.haml
|
|
4
6
|
# May be good to refactor this as well, after the class behaviour is refactored.
|
|
5
7
|
INTERVALS = [
|
|
6
|
-
{:
|
|
7
|
-
|
|
8
|
-
{:code => 'week_of_month', :name => 'week of month', :description =>
|
|
9
|
-
'Weekdays selected will be chosen in their {{ord}} occurance every month,
|
|
8
|
+
{ code: 'week', name: 'week(s)', description: 'Weekdays selected will be chosen every {{n}} weeks for the date range' },
|
|
9
|
+
{ code: 'week_of_month', name: 'week of month', description: '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
|
|
12
|
-
to Thursday 1st and Wednesday 7th'}
|
|
13
|
-
]
|
|
12
|
+
to Thursday 1st and Wednesday 7th' }
|
|
13
|
+
].freeze
|
|
14
14
|
|
|
15
|
-
attr_accessor
|
|
15
|
+
attr_accessor :multiple_dates, :from, :to, :select, :dates, :interval, :weekdays
|
|
16
16
|
|
|
17
17
|
def initialize(options)
|
|
18
18
|
@multiple_dates = options[:multiple_dates] || false
|
|
@@ -28,8 +28,8 @@ module Timely
|
|
|
28
28
|
|
|
29
29
|
def process_date(date)
|
|
30
30
|
case date
|
|
31
|
-
when Date
|
|
32
|
-
when NilClass
|
|
31
|
+
when Date then date
|
|
32
|
+
when NilClass then nil
|
|
33
33
|
when String
|
|
34
34
|
date !~ /[^[:space:]]/ ? nil : date.to_date
|
|
35
35
|
end
|
|
@@ -53,7 +53,7 @@ module Timely
|
|
|
53
53
|
# so every friday and saturday each fornight
|
|
54
54
|
def choose_dates
|
|
55
55
|
# Not multiple dates - just return the From date.
|
|
56
|
-
return [@from]
|
|
56
|
+
return [@from] unless @multiple_dates
|
|
57
57
|
|
|
58
58
|
# Multiple dates - return the array, adjusted as per input
|
|
59
59
|
all_days = (@from..@to).to_a
|
|
@@ -66,21 +66,21 @@ module Timely
|
|
|
66
66
|
days = @specific_dates.gsub(/\s/, '').split(',')
|
|
67
67
|
days.map(&:to_date)
|
|
68
68
|
when 'weekdays'
|
|
69
|
-
raise DateChooserException,
|
|
70
|
-
raise DateChooserException,
|
|
69
|
+
raise DateChooserException, 'No days of the week selected' if @weekdays.weekdays.empty?
|
|
70
|
+
raise DateChooserException, 'No weekly interval selected' if @interval&.empty?
|
|
71
71
|
|
|
72
72
|
all_days.select do |date|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
73
|
+
next unless @weekdays.has_day?(date.wday)
|
|
74
|
+
|
|
75
|
+
case @interval[:unit]
|
|
76
|
+
when 'week'
|
|
77
|
+
# 0 = first week, 1 = second week, 2 = third week, etc.
|
|
78
|
+
nth_week = (date - @from).to_i / 7
|
|
79
|
+
# true every 2nd week (0, 2, 4, 6, etc.)
|
|
80
|
+
(nth_week % @interval[:level].to_i).zero?
|
|
81
|
+
when 'week_of_month'
|
|
82
|
+
week = @interval[:level].to_i
|
|
83
|
+
(date.mday > (week - 1) * 7 && date.mday <= week * 7)
|
|
84
84
|
end
|
|
85
85
|
end
|
|
86
86
|
else
|
|
@@ -89,15 +89,14 @@ module Timely
|
|
|
89
89
|
end
|
|
90
90
|
|
|
91
91
|
private
|
|
92
|
+
|
|
92
93
|
def validate
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
raise DateChooserException, "Start Date is after End Date" if @from > @to
|
|
98
|
-
end
|
|
94
|
+
raise DateChooserException, 'A Start Date is required' unless @from
|
|
95
|
+
raise DateChooserException, 'Start Date is after End Date' if @multiple_dates && @to && @from > @to
|
|
96
|
+
|
|
97
|
+
@to ||= @from if @multiple_dates
|
|
99
98
|
end
|
|
100
99
|
end
|
|
101
100
|
|
|
102
|
-
class DateChooserException <
|
|
101
|
+
class DateChooserException < RuntimeError; end
|
|
103
102
|
end
|
data/lib/timely/date_range.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Timely
|
|
4
4
|
class DateRange < ::Range
|
|
@@ -15,14 +15,14 @@ module Timely
|
|
|
15
15
|
super(args.first.to_date, args.last.to_date)
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
alias start_date first
|
|
19
|
+
alias end_date last
|
|
20
20
|
|
|
21
21
|
def self.validate_range(first, last)
|
|
22
|
-
raise ArgumentError,
|
|
23
|
-
raise ArgumentError,
|
|
24
|
-
raise ArgumentError,
|
|
25
|
-
raise ArgumentError,
|
|
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
26
|
end
|
|
27
27
|
|
|
28
28
|
def self.from_params(start_date, duration = nil)
|
|
@@ -33,19 +33,18 @@ module Timely
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def intersecting_dates(date_range)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
end
|
|
36
|
+
r_start = [start_date, date_range.first].max
|
|
37
|
+
r_end = [end_date, date_range.last].min
|
|
38
|
+
|
|
39
|
+
return [] if r_end < r_start
|
|
40
|
+
|
|
41
|
+
r_start..r_end
|
|
43
42
|
end
|
|
44
43
|
|
|
45
44
|
def number_of_nights
|
|
46
45
|
((last - first) + 1).to_i
|
|
47
46
|
end
|
|
48
|
-
|
|
47
|
+
alias duration number_of_nights
|
|
49
48
|
|
|
50
49
|
def to_s(fmt = '%b %Y', date_fmt = '%Y-%m-%d')
|
|
51
50
|
Timely::DateRange.to_s(first, last, fmt, date_fmt)
|
|
@@ -65,21 +64,20 @@ module Timely
|
|
|
65
64
|
"#{first.strftime(month_fmt)} to #{last.strftime(month_fmt)}"
|
|
66
65
|
end
|
|
67
66
|
else
|
|
68
|
-
"#{first.strftime(fmt)} to #{last.strftime(fmt)}#{
|
|
67
|
+
"#{first.strftime(fmt)} to #{last.strftime(fmt)}#{' (inclusive)' if is_date}"
|
|
69
68
|
end
|
|
70
69
|
elsif first
|
|
71
70
|
"on or after #{first.strftime(fmt)}"
|
|
72
71
|
elsif last
|
|
73
72
|
"on or before #{last.strftime(fmt)}"
|
|
74
73
|
else
|
|
75
|
-
|
|
74
|
+
'no date range'
|
|
76
75
|
end
|
|
77
76
|
end
|
|
78
77
|
|
|
79
|
-
|
|
80
78
|
private
|
|
81
79
|
|
|
82
|
-
def self.default_date_format
|
|
80
|
+
private_class_method def self.default_date_format
|
|
83
81
|
# ::Date as we want Ruby's Date not Timely::Date
|
|
84
82
|
date_format = ::Date::DATE_FORMATS[:short] if ::Date.const_defined?('DATE_FORMATS')
|
|
85
83
|
date_format || '%Y-%m-%d'
|
data/lib/timely/date_time.rb
CHANGED