by_star 2.2.1 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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