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