date_values 0.2.0 → 0.2.1
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/CHANGELOG.md +8 -0
- data/README.md +42 -2
- data/lib/date_values/configuration.rb +19 -0
- data/lib/date_values/month_day.rb +20 -3
- data/lib/date_values/time_of_day.rb +31 -0
- data/lib/date_values/version.rb +1 -1
- data/lib/date_values/year_month.rb +16 -0
- data/lib/date_values.rb +1 -0
- data/sig/date_values.rbs +35 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2fcd39df5c13a6c209d893be43a2be980a20219c5e02c5cc1283a67ba84cf07e
|
|
4
|
+
data.tar.gz: 16ddf29780a17802e64bef957362fe4588fe4e1c9bd67af9a95798d4c65f1379
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b0611c9270e1237268eb2a1d17cca321455bebca402afc5ce4730922171364948498759deba7ba471474657aa2e445b066d7ab26b33e23318f6848bb95363e6b
|
|
7
|
+
data.tar.gz: 664a70b1c75f04341ba490823ae76073bc7d5618493497d7e64c513e3de8c198ae67b0c8ce84549fca3100608922fc79f8b63592180c529be468e45300082e1f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.2.1] - 2026-03-21
|
|
4
|
+
|
|
5
|
+
- Add `TimeOfDay` arithmetic (`+`, `-`), `advance`, `change`, `to_seconds`, `.from_seconds`
|
|
6
|
+
- Add `YearMonth#advance`, `YearMonth#change`, `YearMonth#days`
|
|
7
|
+
- Add `MonthDay#change`
|
|
8
|
+
- Add `#as_json` to all value classes
|
|
9
|
+
- Add `DateValues.config.month_day_order` for locale-dependent `MonthDay.parse`
|
|
10
|
+
|
|
3
11
|
## [0.2.0] - 2026-03-20
|
|
4
12
|
|
|
5
13
|
- **Breaking**: Rails integration extracted to [date_values-rails](https://github.com/ursm/date_values-rails). `require 'date_values/rails'` now requires installing `date_values-rails` gem.
|
data/README.md
CHANGED
|
@@ -23,6 +23,7 @@ include DateValues
|
|
|
23
23
|
ym = YearMonth.new(2026, 3)
|
|
24
24
|
ym.to_s # => "2026-03"
|
|
25
25
|
ym.to_date # => #<Date: 2026-03-01>
|
|
26
|
+
ym.days # => 31
|
|
26
27
|
|
|
27
28
|
YearMonth.from(Date.today) # => #<DateValues::YearMonth 2026-03>
|
|
28
29
|
YearMonth.parse('2026-03') # => #<DateValues::YearMonth 2026-03>
|
|
@@ -32,6 +33,9 @@ ym + 1 # => #<DateValues::YearMonth 2026-04>
|
|
|
32
33
|
ym - 1 # => #<DateValues::YearMonth 2026-02>
|
|
33
34
|
YearMonth.new(2026, 3) - YearMonth.new(2025, 1) # => 14
|
|
34
35
|
|
|
36
|
+
ym.advance(years: 1, months: 2) # => #<DateValues::YearMonth 2027-05>
|
|
37
|
+
ym.change(year: 2025) # => #<DateValues::YearMonth 2025-03>
|
|
38
|
+
|
|
35
39
|
# Range support
|
|
36
40
|
(YearMonth.new(2026, 1)..YearMonth.new(2026, 3)).to_a
|
|
37
41
|
# => [#<DateValues::YearMonth 2026-01>, #<DateValues::YearMonth 2026-02>, #<DateValues::YearMonth 2026-03>]
|
|
@@ -48,7 +52,9 @@ md.to_date(2026) # => #<Date: 2026-03-19>
|
|
|
48
52
|
|
|
49
53
|
MonthDay.from(Date.today) # => #<DateValues::MonthDay --03-20>
|
|
50
54
|
MonthDay.parse('--03-19') # => #<DateValues::MonthDay --03-19>
|
|
51
|
-
MonthDay.parse('3/19') # also works
|
|
55
|
+
MonthDay.parse('3/19') # also works (month/day order by default)
|
|
56
|
+
|
|
57
|
+
md.change(month: 12) # => #<DateValues::MonthDay --12-19>
|
|
52
58
|
|
|
53
59
|
# Range membership
|
|
54
60
|
summer = MonthDay.new(6, 1)..MonthDay.new(8, 31)
|
|
@@ -66,6 +72,16 @@ TimeOfDay.new(14, 30, 45).to_s # => "14:30:45"
|
|
|
66
72
|
TimeOfDay.from(Time.now) # => #<DateValues::TimeOfDay 14:30>
|
|
67
73
|
TimeOfDay.parse('14:30') # => #<DateValues::TimeOfDay 14:30>
|
|
68
74
|
|
|
75
|
+
tod + 3600 # => #<DateValues::TimeOfDay 15:30>
|
|
76
|
+
tod - 1800 # => #<DateValues::TimeOfDay 14:00>
|
|
77
|
+
tod.advance(hours: 2, minutes: 15) # => #<DateValues::TimeOfDay 16:45>
|
|
78
|
+
tod.change(minute: 0) # => #<DateValues::TimeOfDay 14:00>
|
|
79
|
+
tod.to_seconds # => 52200
|
|
80
|
+
TimeOfDay.from_seconds(52200) # => #<DateValues::TimeOfDay 14:30>
|
|
81
|
+
|
|
82
|
+
# Wraps at 24h boundaries
|
|
83
|
+
TimeOfDay.new(23, 30) + 3600 # => #<DateValues::TimeOfDay 00:30>
|
|
84
|
+
|
|
69
85
|
# Range membership
|
|
70
86
|
business_hours = TimeOfDay.new(9, 0)..TimeOfDay.new(17, 0)
|
|
71
87
|
business_hours.cover?(TimeOfDay.new(12, 30)) # => true
|
|
@@ -92,9 +108,33 @@ in { hour: (9..17) }
|
|
|
92
108
|
end
|
|
93
109
|
```
|
|
94
110
|
|
|
111
|
+
### JSON
|
|
112
|
+
|
|
113
|
+
All classes implement `#as_json`, returning the same string as `#to_s`:
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
YearMonth.new(2026, 3).as_json # => "2026-03"
|
|
117
|
+
MonthDay.new(3, 19).as_json # => "--03-19"
|
|
118
|
+
TimeOfDay.new(14, 30).as_json # => "14:30"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Configuration
|
|
122
|
+
|
|
123
|
+
### MonthDay parse order
|
|
124
|
+
|
|
125
|
+
By default, `MonthDay.parse` interprets ambiguous formats like `"3/19"` as month/day. For day/month (European convention):
|
|
126
|
+
|
|
127
|
+
```ruby
|
|
128
|
+
DateValues.config.month_day_order = :day_first
|
|
129
|
+
|
|
130
|
+
MonthDay.parse('19/3') # => #<DateValues::MonthDay --03-19>
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
ISO 8601 format (`--MM-DD`) is always month/day regardless of this setting.
|
|
134
|
+
|
|
95
135
|
## Rails Integration
|
|
96
136
|
|
|
97
|
-
See [date_values-rails](https://github.com/ursm/date_values-rails) for ActiveModel/ActiveRecord type casting, validation, and
|
|
137
|
+
See [date_values-rails](https://github.com/ursm/date_values-rails) for ActiveModel/ActiveRecord type casting, validation, I18n, and ActiveJob support.
|
|
98
138
|
|
|
99
139
|
## License
|
|
100
140
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DateValues
|
|
4
|
+
class Configuration
|
|
5
|
+
attr_accessor :month_day_order
|
|
6
|
+
|
|
7
|
+
def initialize
|
|
8
|
+
@month_day_order = :month_first
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.config
|
|
13
|
+
@config ||= Configuration.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.configure
|
|
17
|
+
yield config
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -19,9 +19,18 @@ module DateValues
|
|
|
19
19
|
|
|
20
20
|
def self.parse(str)
|
|
21
21
|
case str
|
|
22
|
-
when /\A--(\d{1,2})-(\d{1,2})\z/
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
when /\A--(\d{1,2})-(\d{1,2})\z/
|
|
23
|
+
new($1.to_i, $2.to_i)
|
|
24
|
+
when /\A(\d{1,2})[\/\-](\d{1,2})\z/
|
|
25
|
+
a, b = $1.to_i, $2.to_i
|
|
26
|
+
|
|
27
|
+
if DateValues.config.month_day_order == :day_first
|
|
28
|
+
new(b, a)
|
|
29
|
+
else
|
|
30
|
+
new(a, b)
|
|
31
|
+
end
|
|
32
|
+
else
|
|
33
|
+
raise ArgumentError, "invalid MonthDay: #{str}"
|
|
25
34
|
end
|
|
26
35
|
end
|
|
27
36
|
|
|
@@ -31,6 +40,10 @@ module DateValues
|
|
|
31
40
|
[month, day] <=> [other.month, other.day]
|
|
32
41
|
end
|
|
33
42
|
|
|
43
|
+
def change(month: self.month, day: self.day)
|
|
44
|
+
self.class.new(month, day)
|
|
45
|
+
end
|
|
46
|
+
|
|
34
47
|
def strftime(format)
|
|
35
48
|
# 2000 is a leap year, so Feb 29 works
|
|
36
49
|
Date.new(2000, month, day).strftime(format)
|
|
@@ -40,6 +53,10 @@ module DateValues
|
|
|
40
53
|
Date.new(year, month, day)
|
|
41
54
|
end
|
|
42
55
|
|
|
56
|
+
def as_json(*)
|
|
57
|
+
to_s
|
|
58
|
+
end
|
|
59
|
+
|
|
43
60
|
def to_s
|
|
44
61
|
format('--%02d-%02d', month, day)
|
|
45
62
|
end
|
|
@@ -29,10 +29,41 @@ module DateValues
|
|
|
29
29
|
[hour, minute, second] <=> [other.hour, other.minute, other.second]
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
+
def +(seconds)
|
|
33
|
+
self.class.from_seconds((to_seconds + seconds) % 86_400)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def -(seconds)
|
|
37
|
+
self + (-seconds)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def advance(hours: 0, minutes: 0, seconds: 0)
|
|
41
|
+
self + (hours * 3600 + minutes * 60 + seconds)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def change(hour: self.hour, minute: self.minute, second: self.second)
|
|
45
|
+
self.class.new(hour, minute, second)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def to_seconds
|
|
49
|
+
hour * 3600 + minute * 60 + second
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.from_seconds(total)
|
|
53
|
+
total = total % 86_400
|
|
54
|
+
h, rest = total.divmod(3600)
|
|
55
|
+
m, s = rest.divmod(60)
|
|
56
|
+
new(h, m, s)
|
|
57
|
+
end
|
|
58
|
+
|
|
32
59
|
def strftime(format)
|
|
33
60
|
Time.new(2000, 1, 1, hour, minute, second).strftime(format)
|
|
34
61
|
end
|
|
35
62
|
|
|
63
|
+
def as_json(*)
|
|
64
|
+
to_s
|
|
65
|
+
end
|
|
66
|
+
|
|
36
67
|
def to_s
|
|
37
68
|
if second.zero?
|
|
38
69
|
format('%02d:%02d', hour, minute)
|
data/lib/date_values/version.rb
CHANGED
|
@@ -49,6 +49,18 @@ module DateValues
|
|
|
49
49
|
self + 1
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
def advance(years: 0, months: 0)
|
|
53
|
+
self + (years * 12 + months)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def change(year: self.year, month: self.month)
|
|
57
|
+
self.class.new(year, month)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def days
|
|
61
|
+
Date.new(year, month, -1).day
|
|
62
|
+
end
|
|
63
|
+
|
|
52
64
|
def strftime(format)
|
|
53
65
|
to_date.strftime(format)
|
|
54
66
|
end
|
|
@@ -57,6 +69,10 @@ module DateValues
|
|
|
57
69
|
Date.new(year, month, 1)
|
|
58
70
|
end
|
|
59
71
|
|
|
72
|
+
def as_json(*)
|
|
73
|
+
to_s
|
|
74
|
+
end
|
|
75
|
+
|
|
60
76
|
def to_s
|
|
61
77
|
format('%04d-%02d', year, month)
|
|
62
78
|
end
|
data/lib/date_values.rb
CHANGED
data/sig/date_values.rbs
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
module DateValues
|
|
2
2
|
VERSION: String
|
|
3
3
|
|
|
4
|
+
def self.config: () -> Configuration
|
|
5
|
+
def self.configure: () { (Configuration) -> void } -> void
|
|
6
|
+
|
|
7
|
+
class Configuration
|
|
8
|
+
attr_accessor month_day_order: :month_first | :day_first
|
|
9
|
+
|
|
10
|
+
def initialize: () -> void
|
|
11
|
+
end
|
|
12
|
+
|
|
4
13
|
class YearMonth
|
|
5
14
|
include Comparable
|
|
6
15
|
|
|
@@ -23,10 +32,18 @@ module DateValues
|
|
|
23
32
|
|
|
24
33
|
def succ: () -> YearMonth
|
|
25
34
|
|
|
35
|
+
def advance: (?years: Integer, ?months: Integer) -> YearMonth
|
|
36
|
+
|
|
37
|
+
def change: (?year: Integer, ?month: Integer) -> YearMonth
|
|
38
|
+
|
|
39
|
+
def days: () -> Integer
|
|
40
|
+
|
|
26
41
|
def strftime: (String format) -> String
|
|
27
42
|
|
|
28
43
|
def to_date: () -> Date
|
|
29
44
|
|
|
45
|
+
def as_json: (*untyped) -> String
|
|
46
|
+
|
|
30
47
|
def to_s: () -> String
|
|
31
48
|
|
|
32
49
|
def inspect: () -> String
|
|
@@ -47,10 +64,14 @@ module DateValues
|
|
|
47
64
|
def <=>: (MonthDay other) -> Integer
|
|
48
65
|
| (untyped other) -> nil
|
|
49
66
|
|
|
67
|
+
def change: (?month: Integer, ?day: Integer) -> MonthDay
|
|
68
|
+
|
|
50
69
|
def strftime: (String format) -> String
|
|
51
70
|
|
|
52
71
|
def to_date: (Integer year) -> Date
|
|
53
72
|
|
|
73
|
+
def as_json: (*untyped) -> String
|
|
74
|
+
|
|
54
75
|
def to_s: () -> String
|
|
55
76
|
|
|
56
77
|
def inspect: () -> String
|
|
@@ -71,13 +92,27 @@ module DateValues
|
|
|
71
92
|
|
|
72
93
|
def self.from: (Time time) -> TimeOfDay
|
|
73
94
|
|
|
95
|
+
def self.from_seconds: (Integer total) -> TimeOfDay
|
|
96
|
+
|
|
74
97
|
def self.parse: (String str) -> TimeOfDay
|
|
75
98
|
|
|
76
99
|
def <=>: (TimeOfDay other) -> Integer
|
|
77
100
|
| (untyped other) -> nil
|
|
78
101
|
|
|
102
|
+
def +: (Integer seconds) -> TimeOfDay
|
|
103
|
+
|
|
104
|
+
def -: (Integer seconds) -> TimeOfDay
|
|
105
|
+
|
|
106
|
+
def advance: (?hours: Integer, ?minutes: Integer, ?seconds: Integer) -> TimeOfDay
|
|
107
|
+
|
|
108
|
+
def change: (?hour: Integer, ?minute: Integer, ?second: Integer) -> TimeOfDay
|
|
109
|
+
|
|
110
|
+
def to_seconds: () -> Integer
|
|
111
|
+
|
|
79
112
|
def strftime: (String format) -> String
|
|
80
113
|
|
|
114
|
+
def as_json: (*untyped) -> String
|
|
115
|
+
|
|
81
116
|
def to_s: () -> String
|
|
82
117
|
|
|
83
118
|
def inspect: () -> String
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: date_values
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Keita Urashima
|
|
@@ -20,6 +20,7 @@ files:
|
|
|
20
20
|
- README.md
|
|
21
21
|
- Rakefile
|
|
22
22
|
- lib/date_values.rb
|
|
23
|
+
- lib/date_values/configuration.rb
|
|
23
24
|
- lib/date_values/month_day.rb
|
|
24
25
|
- lib/date_values/time_of_day.rb
|
|
25
26
|
- lib/date_values/version.rb
|