tempora 0.1.2 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8c7a7d910796a3c678069364a7b4ecd5ec076047510fb0ae12214a360849bcb
4
- data.tar.gz: a1c2639026325e11d15985a329169ad1d09d80e4eff423f45c14a64c5b5d3e6a
3
+ metadata.gz: 829bad4acfece329fa910614c27da039a46933e2da7246d091df30fd1463cee5
4
+ data.tar.gz: 6d2d1e27e904b76d6f2661fb8328b8a3bceb83c142ffe376f76d261e66fdea07
5
5
  SHA512:
6
- metadata.gz: c71c88d86a13485cdbf93c793052ad8a04b9a4e76383d31f8e187f09a8e0a76b9f1e69b1cb70db6c58f8a40270586eccb20a2e6ed3bf77705e4c106e385bb4e6
7
- data.tar.gz: 3e8e137aca28e67bf704a99c42205a63052bdeec22c9ddb2d17a0dd29ca061db4809a7667cb8be12f7be474745e37c735e209d5a1fe48aa72aa394bb52dc9b97
6
+ metadata.gz: ff6c9aec13bd9eb4ce86085043887f750101a722d64a30d6b8af43e7e52962632e91b8dbb74561cf0df02d05acb7928234ab892eafbe3fe1930bbe6f05cf64cb
7
+ data.tar.gz: '08cc00d8bbac916783277803a0ef3279a7db353bd3a9e5743d2a0576824939e0b1b1039bea1143120068cf995060ac4bb0d827b553d73a2a368e902d69bbd40a'
data/lib/_timespan.rb ADDED
@@ -0,0 +1,106 @@
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
data/lib/month.rb CHANGED
@@ -1,10 +1,10 @@
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
5
+ class Month < TimePeriod
7
6
  extend Initialization
7
+ include HasWeeks
8
8
 
9
9
  def initialize(year, month)
10
10
  @year = Integer(year)
@@ -38,10 +38,6 @@ class Month
38
38
  self.class.from(start_date.prev_month) # @start_date << 1
39
39
  end
40
40
 
41
- def weeks
42
- Week.from(start_date)..Week.from(end_date)
43
- end
44
-
45
41
  alias_method :month, :number
46
42
  alias_method :succ, :next
47
43
  alias_method :pred, :prev
data/lib/quarter.rb CHANGED
@@ -1,11 +1,12 @@
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
6
+ class Quarter < TimePeriod
8
7
  extend Initialization
8
+ include HasMonths
9
+ include HasWeeks
9
10
 
10
11
  def initialize(year, quarter)
11
12
  @year = Integer(year)
@@ -34,19 +35,14 @@ class Quarter
34
35
 
35
36
  alias_method :succ, :next
36
37
  alias_method :pred, :prev
37
-
38
- def months
39
- Month.from(start_date)..Month.from(end_date)
40
- end
41
-
42
- def weeks
43
- Week.from(start_date)..Week.from(end_date)
44
- end
45
38
 
46
39
  private
47
40
 
48
41
  def self.initialization_parameter(date)
49
- quarter = ((date.month - 1) / 3) + 1
50
- [date.year, quarter]
42
+ [date.year, quarter_from_date(date)]
43
+ end
44
+
45
+ def self.quarter_from_date(date)
46
+ ((date.month - 1) / 3) + 1
51
47
  end
52
48
  end
@@ -0,0 +1,9 @@
1
+ module HasMonths
2
+ def months
3
+ Month.from(start_date)..Month.from(end_date)
4
+ end
5
+
6
+ def each_month(&block)
7
+ months.each(&block)
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ require 'week'
2
+
3
+ module HasWeeks
4
+ def weeks
5
+ Week.from(start_date)..Week.from(end_date)
6
+ end
7
+
8
+ def each_week(&block)
9
+ weeks.each(&block)
10
+ end
11
+ 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.2"
4
+ VERSION = "0.2.0"
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"
data/lib/timeperiod.rb CHANGED
@@ -1,9 +1,14 @@
1
1
  require 'date'
2
2
 
3
- module TimePeriod
3
+ class TimePeriod
4
4
  include Comparable
5
5
 
6
6
  attr_reader :start_date, :end_date, :year, :number
7
+
8
+ def initialize(start_date, end_date)
9
+ @start_date = start_date
10
+ @end_date = end_date
11
+ end
7
12
 
8
13
  def range
9
14
  start_date..end_date
@@ -26,7 +31,7 @@ module TimePeriod
26
31
  end
27
32
 
28
33
  def overlaps?(other)
29
- range.overlaps?(other.range)
34
+ range.overlap?(other.range)
30
35
  end
31
36
 
32
37
  def intersection(other)
@@ -35,7 +40,7 @@ module TimePeriod
35
40
  new_start = [start_date, other.start_date].max
36
41
  new_end = [end_date, other.end_date].min
37
42
 
38
- self.class.new(new_start, new_end)
43
+ TimePeriod.new(new_start, new_end)
39
44
  end
40
45
 
41
46
  def <=>(other)
@@ -45,5 +50,4 @@ module TimePeriod
45
50
  alias_method :begin, :start_date
46
51
  alias_method :end, :end_date
47
52
  alias_method :length, :duration
48
- end
49
-
53
+ end
data/lib/week.rb CHANGED
@@ -1,18 +1,17 @@
1
1
  require_relative 'timeperiod'
2
- require_relative 'initialization'
2
+ require_relative 'tempora/initialization'
3
3
 
4
- class Week
5
- include TimePeriod
4
+ class Week < TimePeriod
6
5
  extend Initialization
7
6
 
8
7
  def initialize(year, week)
9
8
  @year = Integer(year)
10
- @number = Integer(week).clamp(1,52)
9
+ @number = Integer(week)
11
10
 
12
11
  @start_date = Date.commercial(@year, @number, 1)
13
12
  @end_date = start_date + 6
14
13
  end
15
-
14
+
16
15
  def id(seperator="-")
17
16
  "#{year}#{seperator}W#{format('%02d', number)}"
18
17
  end
@@ -31,10 +30,10 @@ class Week
31
30
 
32
31
  alias_method :succ, :next
33
32
  alias_method :pred, :prev
34
-
33
+
35
34
  private
36
35
 
37
36
  def self.initialization_parameter(date)
38
- [date.year, date.cweek]
37
+ [date.cwyear, date.cweek]
39
38
  end
40
39
  end
data/lib/year.rb CHANGED
@@ -1,11 +1,12 @@
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
6
+ class Year < TimePeriod
8
7
  extend Initialization
8
+ include HasWeeks
9
+ include HasMonths
9
10
 
10
11
  def initialize(year)
11
12
  @year = Integer(year)
@@ -29,14 +30,6 @@ class Year
29
30
  def prev
30
31
  self.class.new(year - 1)
31
32
  end
32
-
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
33
 
41
34
  alias_method :succ, :next
42
35
  alias_method :pred, :prev
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tempora
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Power
@@ -20,10 +20,13 @@ files:
20
20
  - LICENSE.txt
21
21
  - README.md
22
22
  - Rakefile
23
- - lib/initialization.rb
23
+ - lib/_timespan.rb
24
24
  - lib/month.rb
25
25
  - lib/quarter.rb
26
26
  - lib/tempora.rb
27
+ - lib/tempora/has_months.rb
28
+ - lib/tempora/has_weeks.rb
29
+ - lib/tempora/initialization.rb
27
30
  - lib/tempora/version.rb
28
31
  - lib/timeperiod.rb
29
32
  - lib/week.rb