timely 0.4.2 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build Status](https://
|
3
|
+
[![Build Status](https://github.com/sealink/timely/workflows/Build%20and%20Test/badge.svg?branch=master)](https://github.com/sealink/timely/actions)
|
4
4
|
[![Coverage Status](https://coveralls.io/repos/sealink/timely/badge.png)](https://coveralls.io/r/sealink/timely)
|
5
|
-
[![Dependency Status](https://gemnasium.com/sealink/timely.png?travis)](https://gemnasium.com/sealink/timely)
|
6
5
|
[![Code Climate](https://codeclimate.com/github/sealink/timely.png)](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