comparison tango/tango/time/Clock.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /*******************************************************************************
2
3 copyright: Copyright (c) 2007 Kris Bell. All rights reserved
4
5 license: BSD style: $(LICENSE)
6
7 version: Feb 2007: Initial release
8
9 author: Kris
10
11 *******************************************************************************/
12
13 module tango.time.Clock;
14
15 public import tango.time.Time;
16
17 private import tango.sys.Common;
18
19 private import tango.core.Exception;
20
21 /******************************************************************************
22
23 Exposes UTC time relative to Jan 1st, 1 AD. These values are
24 based upon a clock-tick of 100ns, giving them a span of greater
25 than 10,000 years. These units of time are the foundation of most
26 time and date functionality in Tango.
27
28 Interval is another type of time period, used for measuring a
29 much shorter duration; typically used for timeout periods and
30 for high-resolution timers. These intervals are measured in
31 units of 1 second, and support fractional units (0.001 = 1ms).
32
33 *******************************************************************************/
34
35 struct Clock
36 {
37 version (Win32)
38 {
39 /***************************************************************
40
41 Return the current time as UTC since the epoch
42
43 ***************************************************************/
44
45 static Time now ()
46 {
47 FILETIME fTime = void;
48 GetSystemTimeAsFileTime (&fTime);
49 return convert (fTime);
50 }
51
52 /***************************************************************
53
54 Set Date fields to represent the current time.
55
56 ***************************************************************/
57
58 static DateTime toDate ()
59 {
60 return toDate (now);
61 }
62
63 /***************************************************************
64
65 Set fields to represent the provided UTC time. Note
66 that the conversion is limited by the underlying OS,
67 and will fail to operate correctly with Time
68 values beyond the domain. On Win32 the earliest
69 representable date is 1601. On linux it is 1970. Both
70 systems have limitations upon future dates also. Date
71 is limited to millisecond accuracy at best.
72
73 ***************************************************************/
74
75 static DateTime toDate (Time time)
76 {
77 DateTime dt = void;
78 SYSTEMTIME sTime = void;
79
80 auto fTime = convert (time);
81 FileTimeToSystemTime (&fTime, &sTime);
82
83 dt.date.year = sTime.wYear;
84 dt.date.month = sTime.wMonth;
85 dt.date.day = sTime.wDay;
86 dt.date.dow = sTime.wDayOfWeek;
87 dt.date.doy = 0;
88 dt.date.era = 0;
89 dt.time.hours = sTime.wHour;
90 dt.time.minutes = sTime.wMinute;
91 dt.time.seconds = sTime.wSecond;
92 dt.time.millis = sTime.wMilliseconds;
93 return dt;
94 }
95
96 /***************************************************************
97
98 Convert Date fields to Time
99
100 Note that the conversion is limited by the underlying
101 OS, and will not operate correctly with Time
102 values beyond the domain. On Win32 the earliest
103 representable date is 1601. On linux it is 1970. Both
104 systems have limitations upon future dates also. Date
105 is limited to millisecond accuracy at best.
106
107 ***************************************************************/
108
109 static Time fromDate (inout DateTime dt)
110 {
111 SYSTEMTIME sTime = void;
112 FILETIME fTime = void;
113
114 sTime.wYear = cast(ushort) dt.date.year;
115 sTime.wMonth = cast(ushort) dt.date.month;
116 sTime.wDayOfWeek = 0;
117 sTime.wDay = cast(ushort) dt.date.day;
118 sTime.wHour = cast(ushort) dt.time.hours;
119 sTime.wMinute = cast(ushort) dt.time.minutes;
120 sTime.wSecond = cast(ushort) dt.time.seconds;
121 sTime.wMilliseconds = cast(ushort) dt.time.millis;
122
123 SystemTimeToFileTime (&sTime, &fTime);
124 return convert (fTime);
125 }
126
127 /***************************************************************
128
129 Convert FILETIME to a Time
130
131 ***************************************************************/
132
133 package static Time convert (FILETIME time)
134 {
135 auto t = *cast(long*) &time;
136 t *= 100 / TimeSpan.NanosecondsPerTick;
137 return Time.epoch1601 + TimeSpan(t);
138 }
139
140 /***************************************************************
141
142 Convert Time to a FILETIME
143
144 ***************************************************************/
145
146 package static FILETIME convert (Time dt)
147 {
148 FILETIME time = void;
149
150 TimeSpan span = dt - Time.epoch1601;
151 assert (span >= TimeSpan.zero);
152 *cast(long*) &time.dwLowDateTime = span.ticks;
153 return time;
154 }
155 }
156
157 version (Posix)
158 {
159 /***************************************************************
160
161 Return the current time as UTC since the epoch
162
163 ***************************************************************/
164
165 static Time now ()
166 {
167 timeval tv = void;
168 if (gettimeofday (&tv, null))
169 throw new PlatformException ("Clock.now :: Posix timer is not available");
170
171 return convert (tv);
172 }
173
174 /***************************************************************
175
176 Set Date fields to represent the current time.
177
178 ***************************************************************/
179
180 static DateTime toDate ()
181 {
182 return toDate (now);
183 }
184
185 /***************************************************************
186
187 Set fields to represent the provided UTC time. Note
188 that the conversion is limited by the underlying OS,
189 and will fail to operate correctly with Time
190 values beyond the domain. On Win32 the earliest
191 representable date is 1601. On linux it is 1970. Both
192 systems have limitations upon future dates also. Date
193 is limited to millisecond accuracy at best.
194
195 **************************************************************/
196
197 static DateTime toDate (Time time)
198 {
199 DateTime dt = void;
200 auto timeval = convert (time);
201 dt.time.millis = timeval.tv_usec / 1000;
202
203 tm t = void;
204 gmtime_r (&timeval.tv_sec, &t);
205
206 dt.date.year = t.tm_year + 1900;
207 dt.date.month = t.tm_mon + 1;
208 dt.date.day = t.tm_mday;
209 dt.date.dow = t.tm_wday;
210 dt.date.doy = 0;
211 dt.date.era = 0;
212 dt.time.hours = t.tm_hour;
213 dt.time.minutes = t.tm_min;
214 dt.time.seconds = t.tm_sec;
215 return dt;
216 }
217
218 /***************************************************************
219
220 Convert Date fields to Time
221
222 Note that the conversion is limited by the underlying
223 OS, and will not operate correctly with Time
224 values beyond the domain. On Win32 the earliest
225 representable date is 1601. On linux it is 1970. Both
226 systems have limitations upon future dates also. Date
227 is limited to millisecond accuracy at best.
228
229 ***************************************************************/
230
231 static Time fromDate (inout DateTime dt)
232 {
233 tm t = void;
234
235 t.tm_year = dt.date.year - 1900;
236 t.tm_mon = dt.date.month - 1;
237 t.tm_mday = dt.date.day;
238 t.tm_hour = dt.time.hours;
239 t.tm_min = dt.time.minutes;
240 t.tm_sec = dt.time.seconds;
241
242 auto seconds = timegm (&t);
243 return Time.epoch1970 +
244 TimeSpan.seconds(seconds) +
245 TimeSpan.millis(dt.time.millis);
246 }
247
248 /***************************************************************
249
250 Convert timeval to a Time
251
252 ***************************************************************/
253
254 package static Time convert (inout timeval tv)
255 {
256 return Time.epoch1970 +
257 TimeSpan.seconds(tv.tv_sec) +
258 TimeSpan.micros(tv.tv_usec);
259 }
260
261 /***************************************************************
262
263 Convert Time to a timeval
264
265 ***************************************************************/
266
267 package static timeval convert (Time time)
268 {
269 timeval tv = void;
270
271 TimeSpan span = time - time.epoch1970;
272 assert (span >= TimeSpan.zero);
273 tv.tv_sec = span.seconds;
274 tv.tv_usec = span.micros % 1_000_000L;
275 return tv;
276 }
277 }
278 }
279
280
281
282 debug (UnitTest)
283 {
284 unittest
285 {
286 auto time = Clock.now;
287 assert (Clock.convert(Clock.convert(time)) is time);
288
289 time -= TimeSpan(time.ticks % TimeSpan.TicksPerSecond);
290 auto date = Clock.toDate(time);
291
292 assert (time is Clock.fromDate(date));
293 }
294 }
295
296 debug (Clock)
297 {
298 void main()
299 {
300 auto time = Clock.now;
301 }
302 }