Merge: rosetta_code: sha1
[nit.git] / lib / date.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Services to manipulate `Date`, `Time` and `DateTime`
16 #
17 # The services are split in 2 classes:
18 #
19 # * `Date` handles the year, month and day parts of the date.
20 # * `Time` handles the time in hours, minutes and seconds.
21 #
22 # These are united in `DateTime` for a precise time in a precise day.
23 #
24 # ~~~
25 # var now = new Time.now
26 # var midnight = new Time(0, 0, 0)
27 # assert now > midnight
28 #
29 # var nine_thirty = new Time(9, 30, 0)
30 # var eleven_twenty = new Time(11, 20, 0)
31 # assert eleven_twenty > nine_thirty
32 #
33 # var pi_day = new Date(2015, 03, 14)
34 # var may_the_fourth = new Date(2015, 5, 4)
35 # assert pi_day < may_the_fourth
36 #
37 # var now_t = new DateTime.now
38 # var epoch = new DateTime(1970, 1, 1, 0, 0, 0)
39 # assert now_t > epoch
40 # ~~~
41 #
42 module date
43
44 # A time of the day, composed of an `hour`, a `minute` and a `second` count
45 class Time
46 super Comparable
47 redef type OTHER: Time
48
49 # The hour part of this time, between 0 and 23
50 var hour: Int
51
52 # The minute within the hour, between 0 and 59
53 var minute: Int
54
55 # The second within the minute, between 0 and 59
56 var second: Int
57
58 # Get the current time of the day
59 init now do
60 var tm = new Tm.localtime
61 hour = tm.hour
62 minute = tm.min
63 second = tm.sec
64 end
65
66 # Get the difference between two times in second
67 fun diff_time(other: Time): Int do
68 return (hour * 3600 + minute * 60 + second) -
69 (other.hour * 3600 + other.minute * 60 + other.second)
70 end
71
72 redef fun ==(d) do return d isa Time and time_eq(d)
73
74 redef fun <(d) do return self.diff_time(d) < 0
75
76 redef fun hash do return hour * 1024 + minute * 64 + second
77
78 private fun time_eq(other: Time): Bool
79 do
80 return hour * 3600 + minute * 60 + second ==
81 other.hour * 3600 + other.minute * 60 + other.second
82 end
83 end
84
85 # A date, composed by a `year`, a `month` and a `day`
86 class Date
87 super Comparable
88 redef type OTHER: Date
89
90 # Year, ex: 1989
91 var year: Int
92
93 # Month as an integer, `1` for January, `2` for February, etc.
94 var month: Int
95
96 # Day of the month
97 var day: Int
98
99 # UTC time zone
100 #
101 # FIXME this value is not yet applied
102 var time_zone = "Z"
103
104 # The date of this day
105 init today do
106 var tm = new Tm.localtime
107 year = 1900 + tm.year
108 month = tm.mon + 1
109 day = tm.mday
110 end
111
112 # `self` formatted according to ISO 8601
113 redef fun to_s do return "{year}-{month}-{day}"
114
115 # Difference in days between `self` and `other`
116 fun diff_days(other: Date): Int
117 do
118 var y_out = year - other.year
119 y_out = y_out * 365
120 var m_out = month - other.month
121 m_out = m_out * 30 # FIXME
122 return day - other.day + m_out + y_out
123 end
124
125 # Difference in months between `self` and `other`
126 fun diff_months(other: Date): Int
127 do
128 var y_out = year - other.year
129 y_out = y_out * 12
130 return month - other.month + y_out
131 end
132
133 # Difference in years between `self` and `other`
134 fun diff_years(other: Date): Int do return year - other.year
135
136 redef fun ==(d) do return d isa Date and self.diff_days(d) == 0
137
138 redef fun hash do return year + month * 1024 + day * 2048
139
140 redef fun <(d) do return self.diff_days(d) < 0
141
142 # Is `self` is between the years of `a` and `b`?
143 private fun is_between_years(a, b: Date): Bool
144 do
145 return (a.year > year and b.year < year) or (b.year > year and a.year < year) or (a.year == year or b.year == year)
146 end
147
148 # Is `self` is between the months of `a` and `b`?
149 private fun is_between_months(a, b: Date) : Bool
150 do
151 if not self.is_between_years(a,b) then return false
152 return (a.month > month and b.month < month) or (b.month > month and a.month < month) or (a.month == month or b.month == month)
153 end
154
155 # Is `self` between `a` and `b`?
156 redef fun is_between(a, b)
157 do
158 if not self.is_between_months(a, b) then return false
159 return (a.day > day and b.day < day) or (b.day > day and a.day < day) or (a.day == day or b.day == day)
160 end
161 end
162
163 # A `Time` in a `Date`
164 class DateTime
165 super Date
166 super Time
167 redef type OTHER: DateTime
168 autoinit year, month, day, hour, minute, second
169
170 # Get the current `DateTime`
171 init now
172 do
173 super
174 today
175 end
176
177 redef fun ==(other) do return other isa DateTime and diff_days(other) == 0 and time_eq(other)
178
179 redef fun to_s do return "{super} {hour}:{minute}:{second}{time_zone}"
180 end