lib: move pseudo-toplevel methods from Object
[nit.git] / lib / core / time.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2008 Floréal Morandat <morandat@lirmm.fr>
4 # Copyright 2014 Alexandre Terrasa <alexandre@moz-code.org>
5 #
6 # This file is free software, which comes along with NIT. This software is
7 # distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
8 # without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
9 # PARTICULAR PURPOSE. You can modify it is you want, provided this header
10 # is kept unaltered, and a notification of the changes is added.
11 # You are allowed to redistribute it and sell it, alone or is a part of
12 # another product.
13
14 # Management of time and dates
15 module time
16
17 import text
18 import stream
19
20 in "C Header" `{
21 #include <time.h>
22 `}
23
24 # Unix time: the number of seconds elapsed since January 1, 1970
25 fun get_time: Int `{ return time(NULL); `}
26
27 redef class Sys
28 # Wait a specific number of second and nanoseconds
29 fun nanosleep(sec, nanosec: Int) `{
30 const struct timespec req = {sec, nanosec};
31 nanosleep(&req, NULL);
32 `}
33 end
34
35 # Time since epoch
36 extern class TimeT `{time_t`}
37
38 # Returns Time since epoch from now.
39 new `{ return time(NULL); `}
40
41 # Returns Time since epoch from `i` (expressed in seconds).
42 new from_i(i: Int) `{ return i; `}
43
44 # Update current time.
45 fun update `{ time(&self); `}
46
47 # Convert `self` to a human readable String.
48 fun ctime: String import NativeString.to_s_with_copy `{
49 return NativeString_to_s_with_copy( ctime(&self) );
50 `}
51
52 # Difference in secondes from start (self if the end time)
53 fun difftime(start: TimeT): Float `{ return difftime(self, start); `}
54
55 redef fun to_s do return ctime.replace("\n", "")
56
57 # Convert self to Int (expressed as seconds since epoch).
58 fun to_i: Int `{ return (int)self; `}
59 end
60
61 # Time structure
62 extern class Tm `{struct tm *`}
63
64 # Create a new Time structure expressed in Coordinated Universal Time (UTC).
65 new gmtime `{
66 struct tm *tm;
67 time_t t = time(NULL);
68 tm = gmtime(&t);
69 return tm;
70 `}
71
72 # Create a new Time structure expressed in UTC from `t`.
73 new gmtime_from_timet(t: TimeT) `{
74 struct tm *tm;
75 tm = gmtime(&t);
76 return tm;
77 `}
78
79 # Create a new Time structure expressed in the local timezone.
80 new localtime `{
81 struct tm *tm;
82 time_t t = time(NULL);
83 tm = localtime(&t);
84 return tm;
85 `}
86
87 # Create a new Time structure expressed in the local timezone from `t`.
88 new localtime_from_timet(t: TimeT) `{
89 struct tm *tm;
90 tm = localtime(&t);
91 return tm;
92 `}
93
94 # Convert `self` as a TimeT.
95 fun to_timet: TimeT `{ return mktime(self); `}
96
97 # Seconds after the minute.
98 fun sec: Int `{ return self->tm_sec; `}
99
100 # Minutes after the hour.
101 fun min: Int `{ return self->tm_min; `}
102
103 # hours since midnight.
104 fun hour: Int `{ return self->tm_hour; `}
105
106 # Day of the month.
107 fun mday: Int `{ return self->tm_mday; `}
108
109 # Months since January.
110 fun mon: Int `{ return self->tm_mon; `}
111
112 # Years since 1900.
113 fun year: Int `{ return self->tm_year; `}
114
115 # Days since Sunday.
116 fun wday: Int `{ return self->tm_wday; `}
117
118 # Days since January 1st.
119 fun yday: Int `{ return self->tm_yday; `}
120
121 # Is `self` in Daylight Saving Time.
122 fun is_dst: Bool `{ return self->tm_isdst; `}
123
124 # Convert `self` to a human readable String.
125 fun asctime: String import NativeString.to_s_with_copy `{
126 return NativeString_to_s_with_copy( asctime(self) );
127 `}
128
129 # Convert `self` to a human readable String corresponding to `format`.
130 # TODO document allowed format.
131 fun strftime(format: String): String import String.to_cstring, NativeString.to_s `{
132 char* buf, *c_format;
133
134 buf = (char*)malloc(100);
135 c_format = String_to_cstring(format);
136
137 strftime(buf, 100, c_format, self);
138 String s = NativeString_to_s_with_copy(buf);
139 free(buf);
140 return s;
141 `}
142
143 redef fun to_s do return asctime.replace("\n", "")
144 end
145
146 # Date using the international format defined by ISO 8601.
147 #
148 # Usage:
149 #
150 # # By default ISODate at today.
151 # var date = new ISODate
152 # var tm = new Tm.localtime
153 # assert date.year == tm.year + 1900
154 # assert date.month == tm.mon + 1
155 # assert date.day == tm.mday
156 #
157 # # ISODate can be initialized from a String.
158 # date = new ISODate.from_string("1970-01-01T00:00:00Z")
159 # assert date.year == 1970
160 # assert date.month == 1
161 # assert date.day == 1
162 #
163 # # ISODate can be printed as String following the ISO format.
164 # assert date.to_s == "1970-01-01T00:00:00Z"
165 #
166 # Note that only the `YYYY-MM-DDTHH:MM:SSZ` is supported for now.
167 #
168 # See <http://www.w3.org/QA/Tips/iso-date>
169 class ISODate
170 super Comparable
171
172 # UTC years as Int.
173 var year: Int is noinit
174
175 # UTC months as Int (`1` for January).
176 var month: Int is noinit
177
178 # UTC days as Int (starting at `1`).
179 var day: Int is noinit
180
181 # UTC hours as Int.
182 var hours: Int is noinit
183
184 # UTC minutes as Int.
185 var minutes: Int is noinit
186
187 # UTC seconds as Int.
188 var seconds: Int is noinit
189
190 # UTC timezone marker.
191 #
192 # Note that I don't know what will happen if you change this value...
193 var timezone = "Z"
194
195 init do
196 var t = new Tm.localtime
197 year = 1900 + t.year
198 month = t.mon + 1
199 day = t.mday
200 hours = t.hour
201 minutes = t.min
202 seconds = t.sec
203 end
204
205 # Init `self` from a ISODate formatted string.
206 init from_string(str: String) do
207 year = str.substring(0, 4).to_i
208 month = str.substring(5, 2).to_i
209 day = str.substring(8, 2).to_i
210 hours = str.substring(11, 2).to_i
211 minutes = str.substring(14, 2).to_i
212 seconds = str.substring(17, 2).to_i
213 timezone = str.substring(19, str.length)
214 end
215
216 redef fun to_s do
217 var buff = new FlatBuffer
218 buff.append year.to_s
219 buff.add '-'
220 if month < 10 then buff.add '0'
221 buff.append month.to_s
222 buff.add '-'
223 if day < 10 then buff.add '0'
224 buff.append day.to_s
225 buff.add 'T'
226 if hours < 10 then buff.add '0'
227 buff.append hours.to_s
228 buff.add ':'
229 if minutes < 10 then buff.add '0'
230 buff.append minutes.to_s
231 buff.add ':'
232 if seconds < 10 then buff.add '0'
233 buff.append seconds.to_s
234 buff.append timezone
235 return buff.write_to_string
236 end
237
238 redef type OTHER: ISODate
239
240 # TODO handle timezones
241 redef fun <(o) do return to_s < o.to_s
242 end