tempora 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/lib/month.rb +36 -34
- data/lib/quarter.rb +34 -32
- data/lib/tempora/has_days.rb +11 -0
- data/lib/tempora/has_months.rb +9 -7
- data/lib/tempora/has_weeks.rb +8 -6
- data/lib/tempora/version.rb +1 -1
- data/lib/tempora.rb +2 -1
- data/lib/timeperiod.rb +39 -39
- data/lib/week.rb +27 -25
- data/lib/year.rb +25 -23
- metadata +3 -3
- data/lib/_timespan.rb +0 -106
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1af2de3467a21cc28a33db0590f6934e0892cd6fca23f51183b16252b5f91016
|
4
|
+
data.tar.gz: d0365bb120ea9e0a42e768382136efff98ab25d88343c3876db913ceafd00a93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d21b7f7290f12435d5e77aae4221022dfa0db3b242ad3506edf9bdd446866bc1db576759ea91f5517c8a0b988f159d42517ddd1656beca618384cb46e66de0b
|
7
|
+
data.tar.gz: efbab1ef415bfb7eaa6ffd6877e07d16efe49219a3376437e451cf4a75c3c6076b2d8fc0f908042d0394fe2392ae144a2ef3859153fd120e3deda523c0192493
|
data/lib/month.rb
CHANGED
@@ -2,49 +2,51 @@ require_relative 'timeperiod'
|
|
2
2
|
require_relative 'tempora/initialization'
|
3
3
|
require_relative 'tempora/has_weeks'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
module Tempora
|
6
|
+
class Month < TimePeriod
|
7
|
+
extend Initialization
|
8
|
+
include HasWeeks
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def initialize(year, month)
|
11
|
+
@year = Integer(year)
|
12
|
+
@number = Integer(month).clamp(1, 12)
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
@start_date = Date.new(@year, @number, 1)
|
15
|
+
@end_date = Date.new(@year, @number, -1)
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
def id(seperator="-")
|
19
|
+
"#{year}#{seperator}#{number.to_s.rjust(2, '0')}"
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
def to_s
|
23
|
+
"#{month_name} #{year}"
|
24
|
+
end
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
def month_name
|
27
|
+
Date::MONTHNAMES[number]
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
def month_abbr
|
31
|
+
Date::ABBR_MONTHNAMES[number]
|
32
|
+
end
|
32
33
|
|
33
|
-
|
34
|
-
|
35
|
-
|
34
|
+
def next
|
35
|
+
self.class.from(start_date.next_month) # @start_date >> 1
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
def prev
|
39
|
+
self.class.from(start_date.prev_month) # @start_date << 1
|
40
|
+
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
alias_method :month, :number
|
43
|
+
alias_method :succ, :next
|
44
|
+
alias_method :pred, :prev
|
44
45
|
|
45
|
-
|
46
|
+
private
|
46
47
|
|
47
|
-
|
48
|
-
|
48
|
+
def self.initialization_parameter(date)
|
49
|
+
[date.year, date.month]
|
50
|
+
end
|
49
51
|
end
|
50
|
-
end
|
52
|
+
end
|
data/lib/quarter.rb
CHANGED
@@ -3,46 +3,48 @@ require_relative 'tempora/initialization'
|
|
3
3
|
require_relative 'tempora/has_months'
|
4
4
|
require_relative 'tempora/has_weeks'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
module Tempora
|
7
|
+
class Quarter < TimePeriod
|
8
|
+
extend Initialization
|
9
|
+
include HasMonths
|
10
|
+
include HasWeeks
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
def initialize(year, quarter)
|
13
|
+
@year = Integer(year)
|
14
|
+
@number = Integer(quarter).clamp(1,4)
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
start_month = (quarter - 1) * 3 + 1
|
17
|
+
@start_date = Date.new(year, start_month, 1)
|
18
|
+
@end_date = @start_date.next_month(3).prev_day
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
def id(seperator="-")
|
22
|
+
"#{year}#{seperator}Q#{number}"
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
def to_s
|
26
|
+
"Q#{number} #{year}"
|
27
|
+
end
|
27
28
|
|
28
|
-
|
29
|
-
|
30
|
-
|
29
|
+
def next
|
30
|
+
self.class.from(start_date >> 3)
|
31
|
+
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
def prev
|
34
|
+
self.class.from(start_date << 3)
|
35
|
+
end
|
35
36
|
|
36
|
-
|
37
|
-
|
37
|
+
alias_method :succ, :next
|
38
|
+
alias_method :pred, :prev
|
38
39
|
|
39
|
-
|
40
|
+
private
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
42
|
+
def self.initialization_parameter(date)
|
43
|
+
[date.year, quarter_from_date(date)]
|
44
|
+
end
|
44
45
|
|
45
|
-
|
46
|
-
|
46
|
+
def self.quarter_from_date(date)
|
47
|
+
((date.month - 1) / 3) + 1
|
48
|
+
end
|
47
49
|
end
|
48
|
-
end
|
50
|
+
end
|
data/lib/tempora/has_months.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
module Tempora
|
2
|
+
module HasMonths
|
3
|
+
def months
|
4
|
+
Month.from(start_date)..Month.from(end_date)
|
5
|
+
end
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
def each_month(&block)
|
8
|
+
months.each(&block)
|
9
|
+
end
|
8
10
|
end
|
9
|
-
end
|
11
|
+
end
|
data/lib/tempora/has_weeks.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
require 'week'
|
2
2
|
|
3
|
-
module
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
module Tempora
|
4
|
+
module HasWeeks
|
5
|
+
def weeks
|
6
|
+
Week.from(start_date)..Week.from(end_date)
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
def each_week(&block)
|
10
|
+
weeks.each(&block)
|
11
|
+
end
|
10
12
|
end
|
11
13
|
end
|
data/lib/tempora/version.rb
CHANGED
data/lib/tempora.rb
CHANGED
data/lib/timeperiod.rb
CHANGED
@@ -1,53 +1,53 @@
|
|
1
1
|
require 'date'
|
2
|
+
require_relative 'tempora/has_days'
|
2
3
|
|
3
|
-
|
4
|
-
|
4
|
+
module Tempora
|
5
|
+
class TimePeriod
|
6
|
+
include Comparable
|
7
|
+
include HasDays
|
5
8
|
|
6
|
-
|
9
|
+
attr_reader :start_date, :end_date, :year, :number
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
def initialize(start_date, end_date)
|
12
|
+
@start_date = start_date
|
13
|
+
@end_date = end_date
|
14
|
+
end
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
+
def range
|
17
|
+
start_date..end_date
|
18
|
+
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
def days
|
22
|
-
range.to_a
|
23
|
-
end
|
20
|
+
def duration
|
21
|
+
(end_date - start_date).to_i + 1
|
22
|
+
end
|
24
23
|
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
def contains?(date)
|
25
|
+
range.cover?(date)
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
def overlaps?(other)
|
29
|
+
range.overlap?(other.range)
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
def intersection(other)
|
38
|
-
return nil unless overlaps?(other)
|
32
|
+
def intersection(other)
|
33
|
+
return nil unless overlaps?(other)
|
39
34
|
|
40
|
-
|
41
|
-
|
35
|
+
new_start = [start_date, other.start_date].max
|
36
|
+
new_end = [end_date, other.end_date].min
|
42
37
|
|
43
|
-
|
44
|
-
|
38
|
+
TimePeriod.new(new_start, new_end)
|
39
|
+
end
|
45
40
|
|
46
|
-
|
47
|
-
|
48
|
-
|
41
|
+
def shift(days)
|
42
|
+
TimePeriod.new(@start_date + days, @end_date + days)
|
43
|
+
end
|
44
|
+
|
45
|
+
def <=>(other)
|
46
|
+
start_date <=> other.start_date
|
47
|
+
end
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
alias_method :begin, :start_date
|
50
|
+
alias_method :end, :end_date
|
51
|
+
alias_method :length, :duration
|
52
|
+
end
|
53
53
|
end
|
data/lib/week.rb
CHANGED
@@ -1,39 +1,41 @@
|
|
1
1
|
require_relative 'timeperiod'
|
2
2
|
require_relative 'tempora/initialization'
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
module Tempora
|
5
|
+
class Week < TimePeriod
|
6
|
+
extend Initialization
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
8
|
+
def initialize(year, week)
|
9
|
+
@year = Integer(year)
|
10
|
+
@number = Integer(week)
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
@start_date = Date.commercial(@year, @number, 1)
|
13
|
+
@end_date = start_date + 6
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def id(seperator="-")
|
17
|
+
"#{year}#{seperator}W#{format('%02d', number)}"
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
20
|
+
def to_s
|
21
|
+
"Week #{number}, #{year}"
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
def next
|
25
|
+
self.class.from(start_date + 7)
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
def prev
|
29
|
+
self.class.from(start_date - 7)
|
30
|
+
end
|
30
31
|
|
31
|
-
|
32
|
-
|
32
|
+
alias_method :succ, :next
|
33
|
+
alias_method :pred, :prev
|
33
34
|
|
34
|
-
|
35
|
+
private
|
35
36
|
|
36
|
-
|
37
|
-
|
37
|
+
def self.initialization_parameter(date)
|
38
|
+
[date.cwyear, date.cweek]
|
39
|
+
end
|
38
40
|
end
|
39
41
|
end
|
data/lib/year.rb
CHANGED
@@ -3,34 +3,36 @@ require_relative 'tempora/initialization'
|
|
3
3
|
require_relative 'tempora/has_months'
|
4
4
|
require_relative 'tempora/has_weeks'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
module Tempora
|
7
|
+
class Year < TimePeriod
|
8
|
+
extend Initialization
|
9
|
+
include HasWeeks
|
10
|
+
include HasMonths
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
def initialize(year)
|
13
|
+
@year = Integer(year)
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
@start_date = Date.new(@year, 1, 1)
|
16
|
+
@end_date = Date.new(@year, 12, 31)
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
|
19
|
+
def id
|
20
|
+
year
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
def to_s
|
24
|
+
year.to_s
|
25
|
+
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
27
|
+
def next
|
28
|
+
self.class.new(year + 1)
|
29
|
+
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
def prev
|
32
|
+
self.class.new(year - 1)
|
33
|
+
end
|
33
34
|
|
34
|
-
|
35
|
-
|
35
|
+
alias_method :succ, :next
|
36
|
+
alias_method :pred, :prev
|
37
|
+
end
|
36
38
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tempora
|
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
|
- Max Power
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-02-
|
10
|
+
date: 2025-02-16 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
description: Tempora is a lightweight Ruby library for handling months, weeks, quarters,
|
13
13
|
and years with intuitive date-based calculations and range support.
|
@@ -20,10 +20,10 @@ files:
|
|
20
20
|
- LICENSE.txt
|
21
21
|
- README.md
|
22
22
|
- Rakefile
|
23
|
-
- lib/_timespan.rb
|
24
23
|
- lib/month.rb
|
25
24
|
- lib/quarter.rb
|
26
25
|
- lib/tempora.rb
|
26
|
+
- lib/tempora/has_days.rb
|
27
27
|
- lib/tempora/has_months.rb
|
28
28
|
- lib/tempora/has_weeks.rb
|
29
29
|
- lib/tempora/initialization.rb
|
data/lib/_timespan.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
require 'date'
|
2
|
-
|
3
|
-
class TimeSpan
|
4
|
-
include Comparable
|
5
|
-
|
6
|
-
attr_reader :start_date, :end_date
|
7
|
-
|
8
|
-
def initialize(start_date, end_date)
|
9
|
-
@start_date = TimeSpan.from_date_like(start_date)
|
10
|
-
@end_date = TimeSpan.from_date_like(end_date)
|
11
|
-
|
12
|
-
raise ArgumentError, "start_date must be before end_date" if @start_date > @end_date
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.from_date_like(date_like)
|
16
|
-
if date_like.respond_to?(:year) && date_like.respond_to?(:month) && date_like.respond_to?(:day)
|
17
|
-
Date.new(date_like.year, date_like.month, date_like.day)
|
18
|
-
else
|
19
|
-
raise ArgumentError, "Invalid date-like object: #{date_like.inspect}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def range
|
24
|
-
@start_date..@end_date
|
25
|
-
end
|
26
|
-
|
27
|
-
def duration
|
28
|
-
(@end_date - @start_date).to_i + 1
|
29
|
-
end
|
30
|
-
|
31
|
-
def overlaps?(other)
|
32
|
-
@start_date <= other.end_date && @end_date >= other.start_date
|
33
|
-
end
|
34
|
-
|
35
|
-
def contains?(date)
|
36
|
-
range.cover?(TimeSpan.from_date_like(date))
|
37
|
-
end
|
38
|
-
|
39
|
-
def shift(days)
|
40
|
-
TimeSpan.new(@start_date + days, @end_date + days)
|
41
|
-
end
|
42
|
-
|
43
|
-
def intersection(other)
|
44
|
-
return nil unless overlaps?(other)
|
45
|
-
|
46
|
-
new_start = [@start_date, other.start_date].max
|
47
|
-
new_end = [@end_date, other.end_date].min
|
48
|
-
|
49
|
-
TimeSpan.new(new_start, new_end)
|
50
|
-
end
|
51
|
-
|
52
|
-
def <=>(other)
|
53
|
-
start_date <=> other.start_date
|
54
|
-
end
|
55
|
-
|
56
|
-
def to_s
|
57
|
-
"#{@start_date} to #{@end_date} (#{duration} days)"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
# 🔹 TimeSpan Class (For Any Date Range)
|
61
|
-
#
|
62
|
-
# This will handle custom periods, like fiscal years, school semesters, or project timelines.
|
63
|
-
#
|
64
|
-
# 🔹 How TimeSpan Works
|
65
|
-
#
|
66
|
-
# ✅ Define Any Custom Date Range
|
67
|
-
# fiscal_year = TimeSpan.new(Date.new(2024, 4, 1), Date.new(2025, 3, 31))
|
68
|
-
# puts fiscal_year.to_s
|
69
|
-
# # => "2024-04-01 to 2025-03-31 (365 days)"
|
70
|
-
# ✅ Check Overlaps
|
71
|
-
# q2 = TimeSpan.new(Date.new(2024, 4, 1), Date.new(2024, 6, 30))
|
72
|
-
# q3 = TimeSpan.new(Date.new(2024, 7, 1), Date.new(2024, 9, 30))
|
73
|
-
# puts q2.overlaps?(q3) # => false
|
74
|
-
# ✅ Check If a Date Falls Within the Range
|
75
|
-
# semester = TimeSpan.new(Date.new(2024, 8, 1), Date.new(2024, 12, 15))
|
76
|
-
# puts semester.contains?(Date.new(2024, 9, 10)) # => true
|
77
|
-
# puts semester.contains?(Date.new(2025, 1, 1)) # => false
|
78
|
-
# ✅ Shift Date Ranges
|
79
|
-
# event = TimeSpan.new(Date.new(2024, 6, 10), Date.new(2024, 6, 15))
|
80
|
-
# puts event.shift(7).to_s
|
81
|
-
# # => "2024-06-17 to 2024-06-22 (6 days)"
|
82
|
-
#
|
83
|
-
# 🔹 Why TimeSpan is Useful
|
84
|
-
#
|
85
|
-
# ✅ Handles custom time ranges (fiscal years, semesters, event durations)
|
86
|
-
# ✅ Works alongside Week, Month, Quarter, and Year
|
87
|
-
# ✅ Supports overlapping checks and shifts
|
88
|
-
#
|
89
|
-
# 🔹 How intersection Works
|
90
|
-
#
|
91
|
-
# ✅ Two Overlapping Periods
|
92
|
-
# t1 = TimeSpan.new(Date.new(2024, 3, 1), Date.new(2024, 3, 20))
|
93
|
-
# t2 = TimeSpan.new(Date.new(2024, 3, 10), Date.new(2024, 3, 25))
|
94
|
-
#
|
95
|
-
# overlap = t1.intersection(t2)
|
96
|
-
# puts overlap.to_s
|
97
|
-
# # => "2024-03-10 to 2024-03-20 (11 days)"
|
98
|
-
# ✅ No Overlap Returns nil
|
99
|
-
# t3 = TimeSpan.new(Date.new(2024, 4, 1), Date.new(2024, 4, 10))
|
100
|
-
# puts t1.intersection(t3)
|
101
|
-
# # => nil
|
102
|
-
# 🔹 Why intersection is Useful
|
103
|
-
#
|
104
|
-
# ✅ Find common time slots (e.g., two employees' available time)
|
105
|
-
# ✅ Determine overlapping project phases
|
106
|
-
# ✅ Works with any time period comparisons
|