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

Generated on Fri Nov 11 18:44:19 2005 for Mango by  doxygen 1.4.0