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