tempora 0.1.3 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df646739fb8d7d27a0bb3eed5a3981c668b300e7f105245cb340a233bf447a54
4
- data.tar.gz: 45821e6f2200f5dc69838086ab76bcedfee33773bf7883dfd5fa82fb9a736195
3
+ metadata.gz: 1af2de3467a21cc28a33db0590f6934e0892cd6fca23f51183b16252b5f91016
4
+ data.tar.gz: d0365bb120ea9e0a42e768382136efff98ab25d88343c3876db913ceafd00a93
5
5
  SHA512:
6
- metadata.gz: 3bce9a11d0bc1fedc9f975392c629ebe449a3ddae1ed50584941d0f3256d4b09729a69da168f7fed2cd04cd34d33457788a3cb00a511e9256687d25a51a76fc1
7
- data.tar.gz: d44541c8c7894193804b6d1fce6adf731c8acfa14ffe2d528487f4c839d66e85d2a01992f7209184d1d9323f4fa32ebbcb79be05364b424f03999d4d0ec0eb4e
6
+ metadata.gz: 5d21b7f7290f12435d5e77aae4221022dfa0db3b242ad3506edf9bdd446866bc1db576759ea91f5517c8a0b988f159d42517ddd1656beca618384cb46e66de0b
7
+ data.tar.gz: efbab1ef415bfb7eaa6ffd6877e07d16efe49219a3376437e451cf4a75c3c6076b2d8fc0f908042d0394fe2392ae144a2ef3859153fd120e3deda523c0192493
data/lib/month.rb CHANGED
@@ -1,58 +1,52 @@
1
1
  require_relative 'timeperiod'
2
- require_relative 'initialization'
3
- require_relative 'week'
2
+ require_relative 'tempora/initialization'
3
+ require_relative 'tempora/has_weeks'
4
4
 
5
- class Month
6
- include TimePeriod
7
- extend Initialization
5
+ module Tempora
6
+ class Month < TimePeriod
7
+ extend Initialization
8
+ include HasWeeks
8
9
 
9
- def initialize(year, month)
10
- @year = Integer(year)
11
- @number = Integer(month).clamp(1, 12)
10
+ def initialize(year, month)
11
+ @year = Integer(year)
12
+ @number = Integer(month).clamp(1, 12)
12
13
 
13
- @start_date = Date.new(@year, @number, 1)
14
- @end_date = Date.new(@year, @number, -1)
15
- end
14
+ @start_date = Date.new(@year, @number, 1)
15
+ @end_date = Date.new(@year, @number, -1)
16
+ end
16
17
 
17
- def id(seperator="-")
18
- "#{year}#{seperator}#{number.to_s.rjust(2, '0')}"
19
- end
18
+ def id(seperator="-")
19
+ "#{year}#{seperator}#{number.to_s.rjust(2, '0')}"
20
+ end
20
21
 
21
- def to_s
22
- "#{month_name} #{year}"
23
- end
22
+ def to_s
23
+ "#{month_name} #{year}"
24
+ end
24
25
 
25
- def month_name
26
- Date::MONTHNAMES[number]
27
- end
26
+ def month_name
27
+ Date::MONTHNAMES[number]
28
+ end
28
29
 
29
- def month_abbr
30
- Date::ABBR_MONTHNAMES[number]
31
- end
30
+ def month_abbr
31
+ Date::ABBR_MONTHNAMES[number]
32
+ end
32
33
 
33
- def next
34
- self.class.from(start_date.next_month) # @start_date >> 1
35
- end
34
+ def next
35
+ self.class.from(start_date.next_month) # @start_date >> 1
36
+ end
36
37
 
37
- def prev
38
- self.class.from(start_date.prev_month) # @start_date << 1
39
- end
40
-
41
- def weeks
42
- Week.from(start_date)..Week.from(end_date)
43
- end
44
-
45
- def each_week(&block)
46
- weeks.each(&block)
47
- end
38
+ def prev
39
+ self.class.from(start_date.prev_month) # @start_date << 1
40
+ end
48
41
 
49
- alias_method :month, :number
50
- alias_method :succ, :next
51
- alias_method :pred, :prev
42
+ alias_method :month, :number
43
+ alias_method :succ, :next
44
+ alias_method :pred, :prev
52
45
 
53
- private
46
+ private
54
47
 
55
- def self.initialization_parameter(date)
56
- [date.year, date.month]
48
+ def self.initialization_parameter(date)
49
+ [date.year, date.month]
50
+ end
57
51
  end
58
- end
52
+ end
data/lib/quarter.rb CHANGED
@@ -1,52 +1,50 @@
1
1
  require_relative 'timeperiod'
2
- require_relative 'initialization'
3
- require_relative 'month'
4
- require_relative 'week'
2
+ require_relative 'tempora/initialization'
3
+ require_relative 'tempora/has_months'
4
+ require_relative 'tempora/has_weeks'
5
5
 
6
- class Quarter
7
- include TimePeriod
8
- extend Initialization
6
+ module Tempora
7
+ class Quarter < TimePeriod
8
+ extend Initialization
9
+ include HasMonths
10
+ include HasWeeks
9
11
 
10
- def initialize(year, quarter)
11
- @year = Integer(year)
12
- @number = Integer(quarter).clamp(1,4)
12
+ def initialize(year, quarter)
13
+ @year = Integer(year)
14
+ @number = Integer(quarter).clamp(1,4)
13
15
 
14
- start_month = (quarter - 1) * 3 + 1
15
- @start_date = Date.new(year, start_month, 1)
16
- @end_date = @start_date.next_month(3).prev_day
17
- end
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
18
20
 
19
- def id(seperator="-")
20
- "#{year}#{seperator}Q#{number}"
21
- end
21
+ def id(seperator="-")
22
+ "#{year}#{seperator}Q#{number}"
23
+ end
22
24
 
23
- def to_s
24
- "Q#{number} #{year}"
25
- end
25
+ def to_s
26
+ "Q#{number} #{year}"
27
+ end
26
28
 
27
- def next
28
- self.class.from(start_date >> 3)
29
- end
29
+ def next
30
+ self.class.from(start_date >> 3)
31
+ end
30
32
 
31
- def prev
32
- self.class.from(start_date << 3)
33
- end
33
+ def prev
34
+ self.class.from(start_date << 3)
35
+ end
34
36
 
35
- alias_method :succ, :next
36
- alias_method :pred, :prev
37
-
38
- def months
39
- Month.from(start_date)..Month.from(end_date)
40
- end
37
+ alias_method :succ, :next
38
+ alias_method :pred, :prev
41
39
 
42
- def weeks
43
- Week.from(start_date)..Week.from(end_date)
44
- end
40
+ private
45
41
 
46
- private
42
+ def self.initialization_parameter(date)
43
+ [date.year, quarter_from_date(date)]
44
+ end
47
45
 
48
- def self.initialization_parameter(date)
49
- quarter = ((date.month - 1) / 3) + 1
50
- [date.year, quarter]
46
+ def self.quarter_from_date(date)
47
+ ((date.month - 1) / 3) + 1
48
+ end
51
49
  end
52
- end
50
+ end
@@ -0,0 +1,11 @@
1
+ module Tempora
2
+ module HasDays
3
+ def days
4
+ range.to_a
5
+ end
6
+
7
+ def each_day(&block)
8
+ range.each(&block)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Tempora
2
+ module HasMonths
3
+ def months
4
+ Month.from(start_date)..Month.from(end_date)
5
+ end
6
+
7
+ def each_month(&block)
8
+ months.each(&block)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ require 'week'
2
+
3
+ module Tempora
4
+ module HasWeeks
5
+ def weeks
6
+ Week.from(start_date)..Week.from(end_date)
7
+ end
8
+
9
+ def each_week(&block)
10
+ weeks.each(&block)
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,3 @@
1
- require 'date'
2
-
3
1
  module Initialization
4
2
  def now
5
3
  from Time.now
@@ -8,7 +6,7 @@ module Initialization
8
6
  alias_method :current, :now
9
7
 
10
8
  def from(date)
11
- new *initialization_parameter(date.to_date)
9
+ new(*initialization_parameter(date.to_date))
12
10
  end
13
11
 
14
12
  private
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tempora
4
- VERSION = "0.1.3"
4
+ VERSION = "0.2.1"
5
5
  end
data/lib/tempora.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require_relative "tempora/version"
4
4
  require_relative "timeperiod"
5
- require_relative "initialization"
6
5
  require_relative "year"
7
6
  require_relative "month"
8
7
  require_relative "week"
@@ -11,5 +10,6 @@ require_relative "quarter"
11
10
 
12
11
  module Tempora
13
12
  class Error < StandardError; end
14
- # Your code goes here...
15
13
  end
14
+
15
+ Object.send(:include, Tempora)
data/lib/timeperiod.rb CHANGED
@@ -1,49 +1,53 @@
1
1
  require 'date'
2
+ require_relative 'tempora/has_days'
2
3
 
3
- module TimePeriod
4
- include Comparable
4
+ module Tempora
5
+ class TimePeriod
6
+ include Comparable
7
+ include HasDays
5
8
 
6
- attr_reader :start_date, :end_date, :year, :number
7
-
8
- def range
9
- start_date..end_date
10
- end
11
-
12
- def duration
13
- (end_date - start_date).to_i + 1
14
- end
9
+ attr_reader :start_date, :end_date, :year, :number
15
10
 
16
- def days
17
- range.to_a
18
- end
11
+ def initialize(start_date, end_date)
12
+ @start_date = start_date
13
+ @end_date = end_date
14
+ end
19
15
 
20
- def each_day(&block)
21
- range.each(&block)
22
- end
16
+ def range
17
+ start_date..end_date
18
+ end
23
19
 
24
- def contains?(date)
25
- range.cover?(date)
26
- end
20
+ def duration
21
+ (end_date - start_date).to_i + 1
22
+ end
27
23
 
28
- def overlaps?(other)
29
- range.overlaps?(other.range)
30
- end
24
+ def contains?(date)
25
+ range.cover?(date)
26
+ end
31
27
 
32
- def intersection(other)
33
- return nil unless overlaps?(other)
28
+ def overlaps?(other)
29
+ range.overlap?(other.range)
30
+ end
34
31
 
35
- new_start = [start_date, other.start_date].max
36
- new_end = [end_date, other.end_date].min
32
+ def intersection(other)
33
+ return nil unless overlaps?(other)
37
34
 
38
- self.class.new(new_start, new_end)
39
- end
35
+ new_start = [start_date, other.start_date].max
36
+ new_end = [end_date, other.end_date].min
37
+
38
+ TimePeriod.new(new_start, new_end)
39
+ end
40
40
 
41
- def <=>(other)
42
- start_date <=> other.start_date
43
- end
41
+ def shift(days)
42
+ TimePeriod.new(@start_date + days, @end_date + days)
43
+ end
44
44
 
45
- alias_method :begin, :start_date
46
- alias_method :end, :end_date
47
- alias_method :length, :duration
48
- end
49
-
45
+ def <=>(other)
46
+ start_date <=> other.start_date
47
+ end
48
+
49
+ alias_method :begin, :start_date
50
+ alias_method :end, :end_date
51
+ alias_method :length, :duration
52
+ end
53
+ end
data/lib/week.rb CHANGED
@@ -1,40 +1,41 @@
1
1
  require_relative 'timeperiod'
2
- require_relative 'initialization'
2
+ require_relative 'tempora/initialization'
3
3
 
4
- class Week
5
- include TimePeriod
6
- extend Initialization
4
+ module Tempora
5
+ class Week < TimePeriod
6
+ extend Initialization
7
7
 
8
- def initialize(year, week)
9
- @year = Integer(year)
10
- @number = Integer(week)
8
+ def initialize(year, week)
9
+ @year = Integer(year)
10
+ @number = Integer(week)
11
11
 
12
- @start_date = Date.commercial(@year, @number, 1)
13
- @end_date = start_date + 6
14
- end
12
+ @start_date = Date.commercial(@year, @number, 1)
13
+ @end_date = start_date + 6
14
+ end
15
15
 
16
- def id(seperator="-")
17
- "#{year}#{seperator}W#{format('%02d', number)}"
18
- end
16
+ def id(seperator="-")
17
+ "#{year}#{seperator}W#{format('%02d', number)}"
18
+ end
19
19
 
20
- def to_s
21
- "Week #{number}, #{year}"
22
- end
20
+ def to_s
21
+ "Week #{number}, #{year}"
22
+ end
23
23
 
24
- def next
25
- self.class.from(start_date + 7)
26
- end
24
+ def next
25
+ self.class.from(start_date + 7)
26
+ end
27
27
 
28
- def prev
29
- self.class.from(start_date - 7)
30
- end
28
+ def prev
29
+ self.class.from(start_date - 7)
30
+ end
31
31
 
32
- alias_method :succ, :next
33
- alias_method :pred, :prev
32
+ alias_method :succ, :next
33
+ alias_method :pred, :prev
34
34
 
35
- private
35
+ private
36
36
 
37
- def self.initialization_parameter(date)
38
- [date.cwyear, date.cweek]
37
+ def self.initialization_parameter(date)
38
+ [date.cwyear, date.cweek]
39
+ end
39
40
  end
40
41
  end
data/lib/year.rb CHANGED
@@ -1,51 +1,38 @@
1
1
  require_relative 'timeperiod'
2
- require_relative 'initialization'
3
- require_relative 'month'
4
- require_relative 'week'
2
+ require_relative 'tempora/initialization'
3
+ require_relative 'tempora/has_months'
4
+ require_relative 'tempora/has_weeks'
5
5
 
6
- class Year
7
- include TimePeriod
8
- extend Initialization
9
-
10
- def initialize(year)
11
- @year = Integer(year)
6
+ module Tempora
7
+ class Year < TimePeriod
8
+ extend Initialization
9
+ include HasWeeks
10
+ include HasMonths
11
+
12
+ def initialize(year)
13
+ @year = Integer(year)
12
14
 
13
- @start_date = Date.new(@year, 1, 1)
14
- @end_date = Date.new(@year, 12, 31)
15
- end
15
+ @start_date = Date.new(@year, 1, 1)
16
+ @end_date = Date.new(@year, 12, 31)
17
+ end
16
18
 
17
- def id
18
- year
19
- end
19
+ def id
20
+ year
21
+ end
20
22
 
21
- def to_s
22
- year.to_s
23
- end
23
+ def to_s
24
+ year.to_s
25
+ end
24
26
 
25
- def next
26
- self.class.new(year + 1)
27
- end
28
-
29
- def prev
30
- self.class.new(year - 1)
31
- end
27
+ def next
28
+ self.class.new(year + 1)
29
+ end
32
30
 
33
- def months
34
- Month.new(year, 1)..Month.new(year, 12)
35
- end
36
-
37
- def weeks
38
- Week.from(start_date)..Week.from(end_date)
39
- end
40
-
41
- def each_month(&block)
42
- months.each(&block)
43
- end
44
-
45
- def each_week(&block)
46
- weeks.each(&block)
47
- end
31
+ def prev
32
+ self.class.new(year - 1)
33
+ end
48
34
 
49
- alias_method :succ, :next
50
- alias_method :pred, :prev
35
+ alias_method :succ, :next
36
+ alias_method :pred, :prev
37
+ end
51
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.1.3
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-15 00:00:00.000000000 Z
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,11 +20,13 @@ files:
20
20
  - LICENSE.txt
21
21
  - README.md
22
22
  - Rakefile
23
- - lib/_timespan.rb
24
- - lib/initialization.rb
25
23
  - lib/month.rb
26
24
  - lib/quarter.rb
27
25
  - lib/tempora.rb
26
+ - lib/tempora/has_days.rb
27
+ - lib/tempora/has_months.rb
28
+ - lib/tempora/has_weeks.rb
29
+ - lib/tempora/initialization.rb
28
30
  - lib/tempora/version.rb
29
31
  - lib/timeperiod.rb
30
32
  - lib/week.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