by_star 2.2.1 → 3.0.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.
Files changed (55) hide show
  1. checksums.yaml +5 -13
  2. data/.gitignore +5 -5
  3. data/.travis.yml +61 -35
  4. data/CHANGELOG.md +44 -35
  5. data/Gemfile +18 -25
  6. data/MIT-LICENSE +20 -20
  7. data/README.md +577 -540
  8. data/Rakefile +18 -18
  9. data/UPGRADING +6 -12
  10. data/by_star.gemspec +34 -32
  11. data/cleaner.rb +24 -24
  12. data/lib/by_star.rb +17 -16
  13. data/lib/by_star/base.rb +68 -70
  14. data/lib/by_star/between.rb +156 -120
  15. data/lib/by_star/directional.rb +37 -33
  16. data/lib/by_star/kernel/date.rb +50 -19
  17. data/lib/by_star/kernel/time.rb +41 -41
  18. data/lib/by_star/normalization.rb +127 -118
  19. data/lib/by_star/orm/active_record/by_star.rb +61 -69
  20. data/lib/by_star/orm/mongoid/by_star.rb +76 -73
  21. data/lib/by_star/orm/mongoid/reorder.rb +23 -0
  22. data/lib/by_star/version.rb +3 -3
  23. data/spec/database.yml +15 -15
  24. data/spec/fixtures/active_record/models.rb +12 -10
  25. data/spec/fixtures/active_record/schema.rb +19 -19
  26. data/spec/fixtures/mongoid/models.rb +31 -29
  27. data/spec/fixtures/shared/seeds.rb +26 -26
  28. data/spec/gemfiles/Gemfile.master +6 -0
  29. data/spec/gemfiles/Gemfile.rails40 +7 -0
  30. data/spec/gemfiles/Gemfile.rails41 +7 -0
  31. data/spec/gemfiles/Gemfile.rails42 +7 -0
  32. data/spec/gemfiles/Gemfile.rails50 +10 -0
  33. data/spec/gemfiles/Gemfile.rails51 +10 -0
  34. data/spec/integration/active_record/active_record_spec.rb +38 -53
  35. data/spec/integration/mongoid/mongoid_spec.rb +37 -46
  36. data/spec/integration/shared/between_times.rb +82 -0
  37. data/spec/integration/shared/by_calendar_month.rb +55 -55
  38. data/spec/integration/shared/by_cweek.rb +54 -0
  39. data/spec/integration/shared/by_day.rb +96 -108
  40. data/spec/integration/shared/by_direction.rb +172 -153
  41. data/spec/integration/shared/by_fortnight.rb +48 -48
  42. data/spec/integration/shared/by_month.rb +50 -50
  43. data/spec/integration/shared/by_quarter.rb +49 -49
  44. data/spec/integration/shared/by_week.rb +54 -54
  45. data/spec/integration/shared/by_weekend.rb +49 -49
  46. data/spec/integration/shared/by_year.rb +48 -48
  47. data/spec/integration/shared/offset_parameter.rb +32 -31
  48. data/spec/integration/shared/order_parameter.rb +36 -0
  49. data/spec/integration/shared/relative.rb +174 -174
  50. data/spec/integration/shared/scope_parameter.rb +73 -72
  51. data/spec/spec_helper.rb +29 -29
  52. data/spec/unit/kernel_date_spec.rb +113 -60
  53. data/spec/unit/kernel_time_spec.rb +57 -57
  54. data/spec/unit/normalization_spec.rb +305 -255
  55. metadata +61 -62
@@ -1,33 +1,37 @@
1
- module ByStar
2
-
3
- module Directional
4
-
5
- def before(*args)
6
- with_by_star_options(*args) do |time, options|
7
- time = ByStar::Normalization.time(time)
8
- before_query(time, options)
9
- end
10
- end
11
- alias_method :before_now, :before
12
-
13
- def after(*args)
14
- with_by_star_options(*args) do |time, options|
15
- time = ByStar::Normalization.time(time)
16
- after_query(time, options)
17
- end
18
- end
19
- alias_method :after_now, :after
20
-
21
- def oldest(*args)
22
- with_by_star_options(*args) do |time, options|
23
- oldest_query(options)
24
- end
25
- end
26
-
27
- def newest(*args)
28
- with_by_star_options(*args) do |time, options|
29
- newest_query(options)
30
- end
31
- end
32
- end
33
- end
1
+ module ByStar
2
+
3
+ module Directional
4
+
5
+ def before(*args)
6
+ with_by_star_options(*args) do |time, options|
7
+ scope = by_star_scope(options)
8
+ field = by_star_start_field(options)
9
+ time = ByStar::Normalization.time(time)
10
+ by_star_before_query(scope, field, time)
11
+ end
12
+ end
13
+ alias_method :before_now, :before
14
+
15
+ def after(*args)
16
+ with_by_star_options(*args) do |time, options|
17
+ scope = by_star_scope(options)
18
+ field = by_star_start_field(options)
19
+ time = ByStar::Normalization.time(time)
20
+ by_star_after_query(scope, field, time)
21
+ end
22
+ end
23
+ alias_method :after_now, :after
24
+
25
+ def oldest(*args)
26
+ with_by_star_options(*args) do |time, options|
27
+ oldest_query(options)
28
+ end
29
+ end
30
+
31
+ def newest(*args)
32
+ with_by_star_options(*args) do |time, options|
33
+ newest_query(options)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,19 +1,50 @@
1
- module ByStar
2
-
3
- module Kernel
4
-
5
- module Date
6
- extend ActiveSupport::Concern
7
-
8
- included do
9
-
10
- # Shim to alias Rails 3 #to_time_in_current_zone to Rails 4 name #in_time_zone
11
- if method_defined?(:to_time_in_current_zone) && !method_defined?(:in_time_zone)
12
- alias_method :in_time_zone, :to_time_in_current_zone
13
- end
14
- end
15
- end
16
- end
17
- end
18
-
19
- ::Date.__send__(:include, ByStar::Kernel::Date)
1
+ module ByStar
2
+
3
+ module Kernel
4
+
5
+ module Date
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+
10
+ # Shim to alias Rails 3 #to_time_in_current_zone to Rails 4 name #in_time_zone
11
+ if method_defined?(:to_time_in_current_zone) && !method_defined?(:in_time_zone)
12
+ alias_method :in_time_zone, :to_time_in_current_zone
13
+ end
14
+ end
15
+
16
+ # A "Weekend" is defined as beginning of Saturday to end of Sunday.
17
+ # The weekend for a given date will be the the next weekend if the day Mon-Thurs,
18
+ # otherwise the current weekend if the day is Fri-Sun.
19
+ def beginning_of_weekend
20
+ beginning_of_week(:monday).advance(days: 5)
21
+ end
22
+
23
+ def end_of_weekend
24
+ beginning_of_weekend + 1
25
+ end
26
+
27
+ # A "Fortnight" is defined as a two week period, with the first fortnight of the
28
+ # year beginning on 1st January.
29
+ def beginning_of_fortnight
30
+ beginning_of_year + 14 * ((self - beginning_of_year) / 14).to_i
31
+ end
32
+
33
+ def end_of_fortnight
34
+ beginning_of_fortnight + 13
35
+ end
36
+
37
+ # A "Calendar Month" is defined as a month as it appears on a calendar, including days form
38
+ # previous/following months which are part of the first/last weeks of the given month.
39
+ def beginning_of_calendar_month(*args)
40
+ beginning_of_month.beginning_of_week(*args)
41
+ end
42
+
43
+ def end_of_calendar_month(*args)
44
+ end_of_month.end_of_week(*args)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ ::Date.__send__(:include, ByStar::Kernel::Date)
@@ -1,41 +1,41 @@
1
- module ByStar
2
-
3
- module Kernel
4
-
5
- module Time
6
-
7
- # A "Weekend" is defined as the 60-hour period from 15:00 Friday to 03:00 Monday.
8
- # The weekend for a given date will be the the next weekend if the day Mon-Thurs,
9
- # otherwise the current weekend if the day is Fri-Sun.
10
- def beginning_of_weekend
11
- beginning_of_week(:monday).advance(:days => 4) + 15.hours
12
- end
13
-
14
- def end_of_weekend
15
- (beginning_of_weekend + 59.hours).end_of_hour
16
- end
17
-
18
- # A "Fortnight" is defined as a two week period, with the first fortnight of the
19
- # year beginning on 1st January.
20
- def beginning_of_fortnight
21
- (beginning_of_year.to_date + 14 * ((self - beginning_of_year) / 2.weeks).to_i).beginning_of_day
22
- end
23
-
24
- def end_of_fortnight
25
- (beginning_of_fortnight.to_date + 13).end_of_day
26
- end
27
-
28
- # A "Calendar Month" is defined as a month as it appears on a calendar, including days form
29
- # previous/following months which are part of the first/last weeks of the given month.
30
- def beginning_of_calendar_month(*args)
31
- beginning_of_month.beginning_of_week(*args)
32
- end
33
-
34
- def end_of_calendar_month(*args)
35
- end_of_month.end_of_week(*args)
36
- end
37
- end
38
- end
39
- end
40
-
41
- ::Time.__send__(:include, ByStar::Kernel::Time)
1
+ module ByStar
2
+
3
+ module Kernel
4
+
5
+ module Time
6
+
7
+ # A "Weekend" is defined as beginning of Saturday to end of Sunday.
8
+ # The weekend for a given date will be the the next weekend if the day Mon-Thurs,
9
+ # otherwise the current weekend if the day is Fri-Sun.
10
+ def beginning_of_weekend
11
+ beginning_of_week(:monday).advance(days: 5)
12
+ end
13
+
14
+ def end_of_weekend
15
+ (beginning_of_weekend + 47.hours).end_of_hour
16
+ end
17
+
18
+ # A "Fortnight" is defined as a two week period, with the first fortnight of the
19
+ # year beginning on 1st January.
20
+ def beginning_of_fortnight
21
+ (beginning_of_year + 1.fortnight * ((self - beginning_of_year) / 1.fortnight).to_i).beginning_of_day
22
+ end
23
+
24
+ def end_of_fortnight
25
+ (beginning_of_fortnight + 13.days).end_of_day
26
+ end
27
+
28
+ # A "Calendar Month" is defined as a month as it appears on a calendar, including days form
29
+ # previous/following months which are part of the first/last weeks of the given month.
30
+ def beginning_of_calendar_month(*args)
31
+ beginning_of_month.beginning_of_week(*args)
32
+ end
33
+
34
+ def end_of_calendar_month(*args)
35
+ end_of_month.end_of_week(*args)
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ ::Time.__send__(:include, ByStar::Kernel::Time)
@@ -1,118 +1,127 @@
1
- module ByStar
2
-
3
- class ParseError < StandardError; end
4
-
5
- module Normalization
6
-
7
- class << self
8
-
9
- def time(value)
10
- case value
11
- when String then time_string(value)
12
- when DateTime then value.to_time
13
- when Date then value.in_time_zone
14
- else value
15
- end
16
- end
17
-
18
- def time_string(value)
19
- defined?(Chronic) ? time_string_chronic(value) : time_string_fallback(value)
20
- end
21
-
22
- def time_string_chronic(value)
23
- Chronic.time_class = Time.zone
24
- Chronic.parse(value) || raise(ByStar::ParseError, "Chronic could not parse String #{value.inspect}")
25
- end
26
-
27
- def time_string_fallback(value)
28
- Time.zone.parse(value) || raise(ByStar::ParseError, "Cannot parse String #{value.inspect}")
29
- end
30
-
31
- def week(value, options={})
32
- value = try_string_to_int(value)
33
- case value
34
- when Fixnum then week_fixnum(value, options)
35
- else time(value)
36
- end
37
- end
38
-
39
- def week_fixnum(value, options={})
40
- raise ParseError, 'Week number must be between 0 and 52' unless value.in?(0..52)
41
- time = Time.zone.local(options[:year] || Time.zone.now.year)
42
- time.beginning_of_year + value.to_i.weeks
43
- end
44
-
45
- def fortnight(value, options={})
46
- value = try_string_to_int(value)
47
- case value
48
- when Fixnum then fortnight_fixnum(value, options)
49
- else time(value)
50
- end
51
- end
52
-
53
- def fortnight_fixnum(value, options={})
54
- raise ParseError, 'Fortnight number must be between 0 and 26' unless value.in?(0..26)
55
- time = Time.zone.local(options[:year] || Time.zone.now.year)
56
- time + (value * 2).weeks
57
- end
58
-
59
- def quarter(value, options={})
60
- value = try_string_to_int(value)
61
- case value
62
- when Fixnum then quarter_fixnum(value, options)
63
- else time(value)
64
- end
65
- end
66
-
67
- def quarter_fixnum(value, options={})
68
- raise ParseError, 'Quarter number must be between 1 and 4' unless value.in?(1..4)
69
- time = Time.zone.local(options[:year] || Time.zone.now.year)
70
- time.beginning_of_year + ((value - 1) * 3).months
71
- end
72
-
73
- def month(value, options={})
74
- value = try_string_to_int(value)
75
- case value
76
- when Fixnum, String then month_fixnum(value, options)
77
- else time(value)
78
- end
79
- end
80
-
81
- def month_fixnum(value, options={})
82
- year = options[:year] || Time.zone.now.year
83
- Time.zone.parse "#{year}-#{value}-01"
84
- rescue
85
- raise ParseError, 'Month must be a number between 1 and 12 or a month name'
86
- end
87
-
88
- def year(value, options={})
89
- value = try_string_to_int(value)
90
- case value
91
- when Fixnum then year_fixnum(value)
92
- else time(value)
93
- end
94
- end
95
-
96
- def year_fixnum(value)
97
- Time.zone.local(extrapolate_year(value))
98
- end
99
-
100
- def extrapolate_year(value)
101
- case value.to_i
102
- when 0..69
103
- 2000 + value
104
- when 70..99
105
- 1900 + value
106
- else
107
- value.to_i
108
- end
109
- end
110
-
111
- def try_string_to_int(value)
112
- value.is_a?(String) ? Integer(value) : value
113
- rescue
114
- value
115
- end
116
- end
117
- end
118
- end
1
+ module ByStar
2
+
3
+ class ParseError < StandardError; end
4
+
5
+ module Normalization
6
+
7
+ class << self
8
+
9
+ def time(value)
10
+ case value
11
+ when String then time_string(value)
12
+ when DateTime then value.to_time
13
+ when Date then value.in_time_zone
14
+ else value
15
+ end
16
+ end
17
+
18
+ def time_string(value)
19
+ defined?(Chronic) ? time_string_chronic(value) : time_string_fallback(value)
20
+ end
21
+
22
+ def time_string_chronic(value)
23
+ Chronic.time_class = Time.zone
24
+ Chronic.parse(value) || raise(ByStar::ParseError, "Chronic could not parse String #{value.inspect}")
25
+ end
26
+
27
+ def time_string_fallback(value)
28
+ Time.zone.parse(value) || raise(ByStar::ParseError, "Cannot parse String #{value.inspect}")
29
+ end
30
+
31
+ def week(value, options={})
32
+ value = try_string_to_int(value)
33
+ case value
34
+ when Integer then week_integer(value, options)
35
+ else time(value)
36
+ end
37
+ end
38
+
39
+ def week_integer(value, options={})
40
+ raise ParseError, 'Week number must be between 0 and 52' unless value.in?(0..52)
41
+ time = Time.zone.local(options[:year] || Time.zone.now.year)
42
+ time.beginning_of_year + value.to_i.weeks
43
+ end
44
+
45
+ def cweek(value, options={})
46
+ _value = value
47
+ if _value.is_a?(Integer)
48
+ raise ParseError, 'cweek number must be between 1 and 53' unless value.in?(1..53)
49
+ _value -= 1
50
+ end
51
+ week(_value, options)
52
+ end
53
+
54
+ def fortnight(value, options={})
55
+ value = try_string_to_int(value)
56
+ case value
57
+ when Integer then fortnight_integer(value, options)
58
+ else time(value)
59
+ end
60
+ end
61
+
62
+ def fortnight_integer(value, options={})
63
+ raise ParseError, 'Fortnight number must be between 0 and 26' unless value.in?(0..26)
64
+ time = Time.zone.local(options[:year] || Time.zone.now.year)
65
+ time + (value * 2).weeks
66
+ end
67
+
68
+ def quarter(value, options={})
69
+ value = try_string_to_int(value)
70
+ case value
71
+ when Integer then quarter_integer(value, options)
72
+ else time(value)
73
+ end
74
+ end
75
+
76
+ def quarter_integer(value, options={})
77
+ raise ParseError, 'Quarter number must be between 1 and 4' unless value.in?(1..4)
78
+ time = Time.zone.local(options[:year] || Time.zone.now.year)
79
+ time.beginning_of_year + ((value - 1) * 3).months
80
+ end
81
+
82
+ def month(value, options={})
83
+ value = try_string_to_int(value)
84
+ case value
85
+ when Integer, String then month_integer(value, options)
86
+ else time(value)
87
+ end
88
+ end
89
+
90
+ def month_integer(value, options={})
91
+ year = options[:year] || Time.zone.now.year
92
+ Time.zone.parse "#{year}-#{value}-01"
93
+ rescue
94
+ raise ParseError, 'Month must be a number between 1 and 12 or a month name'
95
+ end
96
+
97
+ def year(value, options={})
98
+ value = try_string_to_int(value)
99
+ case value
100
+ when Integer then year_integer(value)
101
+ else time(value)
102
+ end
103
+ end
104
+
105
+ def year_integer(value)
106
+ Time.zone.local(extrapolate_year(value))
107
+ end
108
+
109
+ def extrapolate_year(value)
110
+ case value.to_i
111
+ when 0..69
112
+ 2000 + value
113
+ when 70..99
114
+ 1900 + value
115
+ else
116
+ value.to_i
117
+ end
118
+ end
119
+
120
+ def try_string_to_int(value)
121
+ value.is_a?(String) ? Integer(value) : value
122
+ rescue
123
+ value
124
+ end
125
+ end
126
+ end
127
+ end