Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

Epoch.d

Go to the documentation of this file.
00001 /*******************************************************************************
00002 
00003         @file Epoch.d
00004         
00005         Copyright (c) 2004 Kris Bell
00006         
00007         This software is provided 'as-is', without any express or implied
00008         warranty. In no event will the authors be held liable for damages
00009         of any kind arising from the use of this software.
00010         
00011         Permission is hereby granted to anyone to use this software for any 
00012         purpose, including commercial applications, and to alter it and/or 
00013         redistribute it freely, subject to the following restrictions:
00014         
00015         1. The origin of this software must not be misrepresented; you must 
00016            not claim that you wrote the original software. If you use this 
00017            software in a product, an acknowledgment within documentation of 
00018            said product would be appreciated but is not required.
00019 
00020         2. Altered source versions must be plainly marked as such, and must 
00021            not be misrepresented as being the original software.
00022 
00023         3. This notice may not be removed or altered from any distribution
00024            of the source.
00025 
00026         4. Derivative works are permitted, but they must carry this notice
00027            in full and credit the original source.
00028 
00029 
00030                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00031 
00032         
00033         @version        Initial version; May 2005
00034               
00035         @author         Kris
00036 
00037 
00038 *******************************************************************************/
00039 
00040 module mango.sys.Epoch;
00041 
00042 /*******************************************************************************
00043 
00044         Haul in additional O/S specific imports
00045 
00046 *******************************************************************************/
00047 
00048 private import mango.sys.OS;
00049 
00050 version (Posix)
00051 {
00052         extern (C) int mktime (tm *);
00053         extern (C) tm *gmtime (int *);
00054 }
00055 
00056 
00057 /******************************************************************************
00058 
00059         Represents UTC time relative to Jan 1st 1970, and converts between
00060         the native time format (a long integer) and a set of fields. The
00061         native time is accurate to the millisecond level.
00062 
00063         See http://en.wikipedia.org/wiki/Unix_time for details on UTC time.
00064 
00065 ******************************************************************************/
00066 
00067 abstract class Epoch
00068 {
00069         private static long beginTime;
00070 
00071         const long InvalidEpoch = -1;
00072 
00073         /***********************************************************************
00074                      
00075                 A set of fields representing date/time components. This is 
00076                 used to abstract differences between Win32 & Posix platforms.
00077                                            
00078         ***********************************************************************/
00079 
00080         struct Fields
00081         {
00082                 int     year,           // fully defined year ~ e.g. 2005
00083                         month,          // 1 through 12
00084                         day,            // 1 through 31
00085                         hour,           // 0 through 23
00086                         min,            // 0 through 59
00087                         sec,            // 0 through 59
00088                         ms,             // 0 through 999
00089                         dow;            // 0 through 6; sunday == 0
00090 
00091 
00092                 /**************************************************************
00093 
00094                 **************************************************************/
00095 
00096                 private static char[][] Days = 
00097                 [
00098                         "Sunday",
00099                         "Monday",
00100                         "Tuesday",
00101                         "Wednesday",
00102                         "Thursday",
00103                         "Friday",
00104                         "Saturday",
00105                 ];
00106 
00107                 /**************************************************************
00108 
00109                 **************************************************************/
00110 
00111                 private static char[][] Months = 
00112                 [
00113                         "null",
00114                         "January",
00115                         "February",
00116                         "March",
00117                         "April",
00118                         "May",
00119                         "June",
00120                         "July",
00121                         "August",
00122                         "September",
00123                         "October",
00124                         "November",
00125                         "December",
00126                 ];
00127 
00128                 /**************************************************************
00129 
00130                         Set the date-related values
00131 
00132                         year  : fully defined year ~ e.g. 2005
00133                         month : 1 through 12
00134                         day   : 1 through 31
00135                         dow   : 0 through 6; sunday=0 (typically set by O/S)
00136 
00137                 **************************************************************/
00138 
00139                 void setDate (int year, int month, int day, int dow = 0)
00140                 {
00141                         this.year = year;
00142                         this.month = month;
00143                         this.day = day;
00144                         this.dow = dow;
00145                 }
00146 
00147                 /**************************************************************
00148 
00149                         Set the time-related values 
00150 
00151                         hour : 0 through 23
00152                         min  : 0 through 59
00153                         sec  : 0 through 59
00154                         ms   : 0 through 999
00155 
00156                 **************************************************************/
00157 
00158                 void setTime (int hour, int min, int sec, int ms = 0)
00159                 {
00160                         this.hour = hour;
00161                         this.min = min;
00162                         this.sec = sec;
00163                         this.ms = ms;
00164                 }
00165 
00166                 /**************************************************************
00167 
00168                         Retrieve English name for the Day of Week
00169 
00170                 **************************************************************/
00171 
00172                 char[] toDowName ()
00173                 {
00174                         return Days[dow];
00175                 }
00176 
00177                 /**************************************************************
00178 
00179                         Retrieve English name for the month
00180 
00181                 **************************************************************/
00182 
00183                 char[] toMonthName ()
00184                 {
00185                         return Months[month];
00186                 }
00187 
00188                 /***************************************************************
00189 
00190                         Win32 implementation
00191 
00192                 ***************************************************************/
00193 
00194                 version (Win32)
00195                 {
00196                         /*******************************************************
00197 
00198                                 Convert fields to UTC time, and return 
00199                                 milliseconds since epoch
00200 
00201                         *******************************************************/
00202 
00203                         long getUtcTime ()
00204                         {
00205                                 SYSTEMTIME sTime;
00206                                 FILETIME   fTime;
00207 
00208                                 sTime.wYear = year;
00209                                 sTime.wMonth = month;
00210                                 sTime.wDayOfWeek = 0;
00211                                 sTime.wDay = day;
00212                                 sTime.wHour = hour;
00213                                 sTime.wMinute = min;
00214                                 sTime.wSecond = sec;
00215                                 sTime.wMilliseconds = ms;
00216 
00217                                 SystemTimeToFileTime (&sTime, &fTime);
00218 
00219                                 return fromFileTime (&fTime);
00220                         }
00221 
00222                         /*******************************************************
00223 
00224                                 Set fields to represent the provided epoch 
00225                                 time
00226                                 
00227                         *******************************************************/
00228 
00229                         void setUtcTime (long time)
00230                         {
00231                                 SYSTEMTIME sTime;
00232                                 FILETIME   fTime;
00233 
00234                                 toFileTime (&fTime, time);
00235                                 FileTimeToSystemTime (&fTime, &sTime);
00236 
00237                                 year = sTime.wYear;
00238                                 month = sTime.wMonth;
00239                                 day = sTime.wDay;
00240                                 hour = sTime.wHour;
00241                                 min = sTime.wMinute;
00242                                 sec = sTime.wSecond;
00243                                 ms = sTime.wMilliseconds;
00244                                 dow = sTime.wDayOfWeek;
00245                         }
00246 
00247                         /*******************************************************
00248 
00249                                 Set fields to represent a localized version
00250                                 of the provided epoch time
00251 
00252                         *******************************************************/
00253 
00254                         void setLocalTime (long time)
00255                         {
00256                                 FILETIME fTime,
00257                                          local;
00258 
00259                                 toFileTime (&fTime, time);
00260                                 FileTimeToLocalFileTime (&fTime, &local);
00261                                 setUtcTime (fromFileTime (&local));
00262                         }
00263                 }
00264 
00265 
00266                 /***************************************************************
00267 
00268                         Posix implementation
00269 
00270                 ***************************************************************/
00271 
00272                 version (Posix)
00273                 {
00274                         /*******************************************************
00275 
00276                                 Convert fields to UTC time, and return 
00277                                 milliseconds since epoch
00278 
00279                         *******************************************************/
00280 
00281                         long getUtcTime ()
00282                         {
00283                                 tm t;
00284 
00285                                 t.tm_year = year - 1900;
00286                                 t.tm_mon = month - 1;
00287                                 t.tm_mday = day;
00288                                 t.tm_hour = hour;
00289                                 t.tm_min = min;
00290                                 t.tm_sec = sec;
00291                                 return 1000L * cast(long) mktime(&t) + ms;
00292                         }
00293 
00294                         /*******************************************************
00295 
00296                                 Set fields to represent the provided epoch 
00297                                 time
00298 
00299 
00300                         *******************************************************/
00301 
00302                         void setUtcTime (long time)
00303                         {
00304                                 ms = time % 1000;                                
00305                                 int utc = time / 1000;
00306 
00307                                 synchronized (lock)
00308                                              {
00309                                              tm* t = gmtime (&utc);
00310                                              assert (t);
00311 
00312                                              year = t.tm_year + 1900;
00313                                              month = t.tm_mon + 1;
00314                                              day = t.tm_mday;
00315                                              hour = t.tm_hour;
00316                                              min = t.tm_min;
00317                                              sec = t.tm_sec;
00318                                              dow = t.tm_wday;                        
00319                                              }
00320                         }
00321 
00322                         /*******************************************************
00323 
00324                                 Set fields to represent a localized version
00325                                 of the provided epoch time 
00326 
00327                         *******************************************************/
00328 
00329                         void setLocalTime (long time)
00330                         {
00331                                 ms = time % 1000;                                
00332                                 int utc = time / 1000;
00333 
00334                                 synchronized (lock)
00335                                              {
00336                                              tm* t = localtime (&utc);
00337                                              year = t.tm_year + 1900;
00338                                              month = t.tm_mon + 1;
00339                                              day = t.tm_mday;
00340                                              hour = t.tm_hour;
00341                                              min = t.tm_min;
00342                                              sec = t.tm_sec;
00343                                              dow = t.tm_wday;                        
00344                                              }
00345                         }
00346                 }
00347         }
00348 
00349 
00350         /***********************************************************************
00351                 
00352                         Utc time this executable started 
00353 
00354         ***********************************************************************/
00355 
00356         final static long startTime ()
00357         {
00358                 return startTime;
00359         }
00360 
00361 
00362         /***********************************************************************
00363                         
00364                 Basic functions for epoch time
00365 
00366         ***********************************************************************/
00367 
00368         version (Win32)
00369         {
00370                 private static long epochOffset;
00371 
00372                 /***************************************************************
00373                 
00374                         Return the current time as UTC milliseconds since 
00375                         the epoch
00376 
00377                 ***************************************************************/
00378 
00379                 static long utcMilli ()
00380                 {
00381                         FILETIME fTime;
00382 
00383                         GetSystemTimeAsFileTime (&fTime);
00384                         return fromFileTime (&fTime);
00385                 }
00386 
00387                 /***************************************************************
00388                 
00389                         Return the current time as UTC nanoseconds since 
00390                         the epoch
00391 
00392                 ***************************************************************/
00393 
00394                 static long utcNano ()
00395                 {
00396                         FILETIME fTime;
00397 
00398                         GetSystemTimeAsFileTime (&fTime);
00399                         long tmp = (cast(long) fTime.dwHighDateTime) << 32 | 
00400                                                fTime.dwLowDateTime;
00401 
00402                         // convert to nanoseconds
00403                         return (tmp - epochOffset) * 100;
00404                 }
00405 
00406                 /***************************************************************
00407                 
00408                         Return the timezone minutes relative to GMT
00409 
00410                 ***************************************************************/
00411 
00412                 static int tzMinutes ()
00413                 {
00414                         TIME_ZONE_INFORMATION tz;
00415 
00416                         int ret = GetTimeZoneInformation (&tz);
00417                         return -tz.Bias;
00418                 }
00419 
00420                 /***************************************************************
00421                 
00422                         Construct an offset representing epoch time
00423 
00424                 ***************************************************************/
00425 
00426                 static this ()
00427                 {
00428                         SYSTEMTIME sTime;
00429                         FILETIME   fTime;
00430 
00431                         // first second of 1970 ...
00432                         sTime.wYear = 1970;
00433                         sTime.wMonth = 1;
00434                         sTime.wDayOfWeek = 0;
00435                         sTime.wDay = 1;
00436                         sTime.wHour = 0;
00437                         sTime.wMinute = 0;
00438                         sTime.wSecond = 0;
00439                         sTime.wMilliseconds = 0;
00440                         SystemTimeToFileTime (&sTime, &fTime);
00441 
00442                         epochOffset = (cast(long) fTime.dwHighDateTime) << 32 | 
00443                                                   fTime.dwLowDateTime;
00444                         beginTime = utcMilli();
00445                 }
00446 
00447                 /***************************************************************
00448                 
00449                         Convert filetime to epoch time
00450                          
00451                 ***************************************************************/
00452 
00453                 private static long fromFileTime (FILETIME* ft)
00454                 {
00455                         long tmp = (cast(long) ft.dwHighDateTime) << 32 | 
00456                                                ft.dwLowDateTime;
00457 
00458                         // convert to milliseconds
00459                         return (tmp - epochOffset) / 10_000;
00460                 }
00461 
00462                 /***************************************************************
00463                 
00464                         convert epoch time to file time
00465 
00466                 ***************************************************************/
00467 
00468                 private static void toFileTime (FILETIME* ft, long et)
00469                 {
00470                         et = et * 10_000 + epochOffset;
00471 
00472                         ft.dwHighDateTime = et >> 32; 
00473                         ft.dwLowDateTime = et & 0xFFFFFFFF;
00474                 }
00475         }
00476 
00477 
00478         /***********************************************************************
00479                         
00480         ***********************************************************************/
00481 
00482         version (Posix)
00483         {
00484                 // these are exposed via an external library
00485                 extern static int timezone;
00486                 extern static int daylight;
00487 
00488                 private static Object lock;
00489 
00490                 /***************************************************************
00491                 
00492                         Create a synch object for fields.setTime()
00493 
00494                 ***************************************************************/
00495 
00496                 static this()
00497                 {
00498                         lock = new Object;
00499                         beginTime = utcMilli();
00500                 }
00501 
00502                 /***************************************************************
00503                 
00504                         Return the current time as UTC milliseconds since 
00505                         the epoch. 
00506 
00507                ***************************************************************/
00508 
00509                 static long utcMilli ()
00510                 {
00511                         timeval tv;
00512 
00513                         if (gettimeofday (&tv, null))
00514                             throw new Exception ("linux timer is not available");
00515 
00516                         return 1000L * cast(long) tv.tv_sec + tv.tv_usec / 1000;
00517                 }
00518 
00519                 /***************************************************************
00520                 
00521                         Return the current time as UTC nanoseconds since 
00522                         the epoch. 
00523 
00524                ***************************************************************/
00525 
00526                 static long utcNano ()
00527                 {
00528                         timeval tv;
00529 
00530                         if (gettimeofday (&tv, null))
00531                             throw new Exception ("linux timer is not available");
00532 
00533                         return 1_000_000_000L * cast(long) tv.tv_sec + tv.tv_usec * 1000;
00534                 }
00535 
00536                 /***************************************************************
00537                 
00538                         Return the timezone minutes relative to GMT
00539 
00540                 ***************************************************************/
00541 
00542                 static int tzMinutes ()
00543                 {
00544                         // this may need to be negated?
00545                         return timezone / 60;
00546                 }
00547         }
00548 }

Generated on Mon Nov 14 10:59:37 2005 for Mango by  doxygen 1.4.0