Vault
4.1
|
00001 /* 00002 Copyright c1997-2014 Trygve Isaacson. All rights reserved. 00003 This file is part of the Code Vault version 4.1 00004 http://www.bombaydigital.com/ 00005 License: MIT. See LICENSE.md in the Vault top level directory. 00006 */ 00007 00008 #include "vinstant.h" 00009 #include "vtypes_internal.h" 00010 #include "vexception.h" 00011 00012 #include <sys/time.h> 00013 00014 /* 00015 These are the platform-specific implementations of these required 00016 core time functions. 00017 */ 00018 00019 #ifdef VLIBRARY_METROWERKS 00020 static Vs64 _getMSLLocalTimeZoneOffsetMilliseconds() { 00021 /* 00022 When compiling with Metrowerks CodeWarrior on Mac, the MSL library's version of mktime() is incorrect 00023 in that it does not actually do the local time zone conversion. That is, it behaves like timegm(). 00024 We need to work around this bug by subtracting the local time zone offset. 00025 This is sort of the inverse of the problem with VC++ in the other conditionally compiled code above. 00026 FIXME: The remaining issue is that we are referencing the CURRENT tz offset, not the offset at the 00027 time that is being queried; and this seems to always be standard time -- e.g., 8hrs in Oakland, 00028 never 7hrs even in summertime DST. So in summertime this makes us off by 1 hr. 00029 */ 00030 00031 int offsetSeconds = 0; 00032 00033 struct timezone zone; 00034 00035 if (::gettimeofday(NULL, &zone) == 0) { 00036 offsetSeconds = (zone.tz_minuteswest * 60); 00037 } 00038 00039 return CONST_S64(1000) * static_cast<Vs64>(offsetSeconds); 00040 } 00041 #endif 00042 00043 #define INSTANT_STRUCT_FORMAT "%d-%02d-%02d %02d:%02d:%02d.%03d" 00044 00045 // static 00046 Vs64 VInstantStruct::_platform_offsetFromLocalStruct(const VInstantStruct& when) { 00047 struct tm fields; 00048 00049 when.getTmStruct(fields); 00050 00051 //lint -e421 "Caution -- function 'mktime(struct tm *)' is considered dangerous [MISRA Rule 127]" 00052 Vs64 mktimeSeconds = static_cast<Vs64>(::mktime(&fields)); 00053 00054 if (mktimeSeconds == CONST_S64(-1)) { 00055 throw VStackTraceException(VSTRING_FORMAT("VInstantStruct::_platform_offsetFromLocalStruct: time value '" INSTANT_STRUCT_FORMAT "' is out of range.", 00056 when.mYear, when.mMonth, when.mDay, when.mHour, when.mMinute, when.mSecond, when.mMillisecond)); 00057 } 00058 00059 Vs64 resultOffsetMilliseconds = CONST_S64(1000) * mktimeSeconds; 00060 00061 #ifdef VLIBRARY_METROWERKS 00062 resultOffsetMilliseconds += _getMSLLocalTimeZoneOffsetMilliseconds(); 00063 #endif 00064 00065 // tm struct has no milliseconds, so restore input value milliseconds 00066 resultOffsetMilliseconds += (Vs64) when.mMillisecond; 00067 00068 return resultOffsetMilliseconds; 00069 } 00070 00071 // static 00072 void VInstantStruct::_platform_offsetToLocalStruct(Vs64 offset, VInstantStruct& when) { 00073 struct tm fields; 00074 ::memset(&fields, 0, sizeof(fields)); 00075 00076 #ifdef VLIBRARY_METROWERKS 00077 offset -= _getMSLLocalTimeZoneOffsetMilliseconds(); 00078 #endif 00079 00080 VInstantStruct::_threadsafe_localtime(static_cast<time_t>(offset / 1000), &fields); 00081 00082 when.setFromTmStruct(fields, (int)(offset % 1000)); 00083 } 00084 00085 // static 00086 void VInstantStruct::_platform_offsetToUTCStruct(Vs64 offset, VInstantStruct& when) { 00087 struct tm fields; 00088 ::memset(&fields, 0, sizeof(fields)); 00089 00090 VInstantStruct::_threadsafe_gmtime(static_cast<time_t>(offset / 1000), &fields); 00091 00092 when.setFromTmStruct(fields, (int)(offset % 1000)); 00093 } 00094 00095 // static 00096 Vs64 VInstant::_platform_now() { 00097 #ifdef V_INSTANT_SNAPSHOT_IS_UTC 00098 00099 // This means we can get millisecond resolution for VInstant values. 00100 return VInstant::_platform_snapshot(); 00101 00102 #else 00103 00104 // This means we can only get second resolution for VInstant values. 00105 //lint -e418 -e421 "Passing null pointer to function 'time(long *)'" [OK: IEEE POSIX disagrees with lint. NULL is meaningful.] 00106 return (CONST_S64(1000) * static_cast<Vs64>(::time(NULL))); 00107 00108 #endif /* V_INSTANT_SNAPSHOT_IS_UTC */ 00109 } 00110 00111 // static 00112 Vs64 VInstant::_platform_snapshot() { 00113 struct timeval tv; 00114 (void) ::gettimeofday(&tv, NULL); 00115 00116 // We need to be careful to cast to Vs64 or we risk truncation to 32 bits. 00117 return (((Vs64)(tv.tv_sec)) * CONST_S64(1000)) + (Vs64)(tv.tv_usec / 1000); 00118 } 00119