606ccd81d5ba518e26be598e4c3d0261452b8661
[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 redef class Float
36 # Sleep approximately `self` seconds
37 fun sleep `{
38 time_t s = self;
39 long ns = (self-s) * 1000000000.0;
40 const struct timespec req = {s, ns};
41 nanosleep(&req, NULL);
42 `}
43 end
44
45 # Time since epoch
46 extern class TimeT `{time_t`}
47
48 # Returns Time since epoch from now.
49 new `{ return time(NULL); `}
50
51 # Returns Time since epoch from `i` (expressed in seconds).
52 new from_i(i: Int) `{ return i; `}
53
54 # Update current time.
55 fun update `{ time(&self); `}
56
57 # Convert `self` to a human readable String.
58 fun ctime: String import CString.to_s_with_copy `{
59 return CString_to_s_with_copy( ctime(&self) );
60 `}
61
62 # Difference in secondes from start (self if the end time)
63 fun difftime(start: TimeT): Float `{ return difftime(self, start); `}
64
65 redef fun to_s do return ctime.replace("\n", "")
66
67 # Convert self to Int (expressed as seconds since epoch).
68 fun to_i: Int `{ return (int)self; `}
69 end
70
71 # Time structure
72 extern class Tm `{struct tm *`}
73
74 # Create a new Time structure expressed in Coordinated Universal Time (UTC).
75 new gmtime `{
76 struct tm *tm;
77 time_t t = time(NULL);
78 tm = gmtime(&t);
79 return tm;
80 `}
81
82 # Create a new Time structure expressed in UTC from `t`.
83 new gmtime_from_timet(t: TimeT) `{
84 struct tm *tm;
85 tm = gmtime(&t);
86 return tm;
87 `}
88
89 # Create a new Time structure expressed in the local timezone.
90 new localtime `{
91 struct tm *tm;
92 time_t t = time(NULL);
93 tm = localtime(&t);
94 return tm;
95 `}
96
97 # Create a new Time structure expressed in the local timezone from `t`.
98 new localtime_from_timet(t: TimeT) `{
99 struct tm *tm;
100 tm = localtime(&t);
101 return tm;
102 `}
103
104 # Convert `self` as a TimeT.
105 fun to_timet: TimeT `{ return mktime(self); `}
106
107 # Seconds after the minute.
108 fun sec: Int `{ return self->tm_sec; `}
109
110 # Minutes after the hour.
111 fun min: Int `{ return self->tm_min; `}
112
113 # hours since midnight.
114 fun hour: Int `{ return self->tm_hour; `}
115
116 # Day of the month.
117 fun mday: Int `{ return self->tm_mday; `}
118
119 # Months since January.
120 fun mon: Int `{ return self->tm_mon; `}
121
122 # Years since 1900.
123 fun year: Int `{ return self->tm_year; `}
124
125 # Days since Sunday.
126 fun wday: Int `{ return self->tm_wday; `}
127
128 # Days since January 1st.
129 fun yday: Int `{ return self->tm_yday; `}
130
131 # Is `self` in Daylight Saving Time.
132 fun is_dst: Bool `{ return self->tm_isdst; `}
133
134 # Convert `self` to a human readable String.
135 private fun asctime: CString `{ return asctime(self); `}
136
137 # Convert `self` to a human readable String corresponding to `format`.
138 # TODO document allowed format.
139 fun strftime(format: String): String import String.to_cstring, CString.to_s_with_copy `{
140 char* buf, *c_format;
141
142 buf = (char*)malloc(100);
143 c_format = String_to_cstring(format);
144
145 strftime(buf, 100, c_format, self);
146 String s = CString_to_s_with_copy(buf);
147 free(buf);
148 return s;
149 `}
150
151 redef fun to_s do return asctime.to_s_with_copy.replace("\n", "")
152 end
153
154 # Date using the international format defined by ISO 8601.
155 #
156 # Usage:
157 #
158 # # By default ISODate at today.
159 # var date = new ISODate
160 # var tm = new Tm.localtime
161 # assert date.year == tm.year + 1900
162 # assert date.month == tm.mon + 1
163 # assert date.day == tm.mday
164 #
165 # # ISODate can be initialized from a String.
166 # date = new ISODate.from_string("1970-01-01T00:00:00Z")
167 # assert date.year == 1970
168 # assert date.month == 1
169 # assert date.day == 1
170 #
171 # # ISODate can be printed as String following the ISO format.
172 # assert date.to_s == "1970-01-01T00:00:00Z"
173 #
174 # Note that only the `YYYY-MM-DDTHH:MM:SSZ` is supported for now.
175 #
176 # See <http://www.w3.org/QA/Tips/iso-date>
177 class ISODate
178 super Comparable
179
180 # UTC years as Int.
181 var year: Int is noinit
182
183 # UTC months as Int (`1` for January).
184 var month: Int is noinit
185
186 # UTC days as Int (starting at `1`).
187 var day: Int is noinit
188
189 # UTC hours as Int.
190 var hours: Int is noinit
191
192 # UTC minutes as Int.
193 var minutes: Int is noinit
194
195 # UTC seconds as Int.
196 var seconds: Int is noinit
197
198 # UTC timezone marker.
199 #
200 # Note that I don't know what will happen if you change this value...
201 var timezone = "Z"
202
203 init do
204 var t = new Tm.localtime
205 year = 1900 + t.year
206 month = t.mon + 1
207 day = t.mday
208 hours = t.hour
209 minutes = t.min
210 seconds = t.sec
211 end
212
213 # Init `self` from a ISODate formatted string.
214 init from_string(str: String) do
215 year = str.substring(0, 4).to_i
216 month = str.substring(5, 2).to_i
217 day = str.substring(8, 2).to_i
218 hours = str.substring(11, 2).to_i
219 minutes = str.substring(14, 2).to_i
220 seconds = str.substring(17, 2).to_i
221 timezone = str.substring(19, str.length)
222 end
223
224 redef fun to_s do
225 var buff = new FlatBuffer
226 buff.append year.to_s
227 buff.add '-'
228 if month < 10 then buff.add '0'
229 buff.append month.to_s
230 buff.add '-'
231 if day < 10 then buff.add '0'
232 buff.append day.to_s
233 buff.add 'T'
234 if hours < 10 then buff.add '0'
235 buff.append hours.to_s
236 buff.add ':'
237 if minutes < 10 then buff.add '0'
238 buff.append minutes.to_s
239 buff.add ':'
240 if seconds < 10 then buff.add '0'
241 buff.append seconds.to_s
242 buff.append timezone
243 return buff.write_to_string
244 end
245
246 redef type OTHER: ISODate
247
248 # TODO handle timezones
249 redef fun <(o) do return to_s < o.to_s
250 end