00001 /*****************************************************************************\ 00002 * * 00003 * Name : time_stamp * 00004 * Author : Chris Koeritz * 00005 * * 00006 ******************************************************************************* 00007 * Copyright (c) 1995-$now By Author. This program is free software; you can * 00008 * redistribute it and/or modify it under the terms of the GNU General Public * 00009 * License as published by the Free Software Foundation; either version 2 of * 00010 * the License or (at your option) any later version. This is online at: * 00011 * http://www.fsf.org/copyleft/gpl.html * 00012 * Please send any updates to: fred@gruntose.com * 00013 \*****************************************************************************/ 00014 00015 #include "earth_time.h" 00016 #include "time_stamp.h" 00017 00018 #include <basis/environment.h> 00019 #include <basis/mutex.h> 00020 00021 #include <stdlib.h> 00022 #ifdef __WIN32__ 00023 #define _WINSOCKAPI_ // make windows.h happy about winsock. 00024 // #include <windows.h> 00025 #include <winsock2.h> // timeval. 00026 #endif 00027 00028 using namespace basis; 00029 00030 namespace timely { 00031 00032 static mutex &__uptime_synchronizer() { 00033 static mutex uptiming_syncher; 00034 return uptiming_syncher; 00035 } 00036 00037 basis::astring time_stamp::notarize(bool add_space) 00038 { 00039 const time_locus the_time = now(); 00040 astring to_return; 00041 the_time.text_form_long(to_return, clock_time::MILITARY | clock_time::MILLISECONDS); 00042 if (add_space) to_return += " "; 00043 return to_return; 00044 } 00045 00046 time_stamp::time_stamp() : c_stamp(0) { fill_in_time(); } 00047 00048 time_stamp::time_stamp(time_representation offset) 00049 : c_stamp(0) { reset(offset); } 00050 00051 void time_stamp::reset() { fill_in_time(); } 00052 00053 astring time_stamp::text_form(stamp_display_style style) const 00054 { 00055 time_representation stump = c_stamp; 00056 bool past = false; 00057 if (style == STAMP_RELATIVE) { 00058 // adjust the returned time by subtracting the current time. 00059 stump -= get_time_now(); 00060 if (negative(stump)) { 00061 // if we're negative, just note that the stamp is in the past. 00062 past = true; 00063 stump = absolute_value(stump); 00064 } 00065 } 00066 time_representation divisor = 3600 * SECOND_ms; 00067 basis::un_int hours = basis::un_int(stump / divisor); 00068 stump -= divisor * time_representation(hours); 00069 divisor /= 60; 00070 basis::un_int minutes = basis::un_int(stump / divisor); 00071 stump -= divisor * time_representation(minutes); 00072 divisor /= 60; 00073 basis::un_int seconds = basis::un_int(stump / divisor); 00074 stump -= divisor * time_representation(seconds); 00075 basis::un_int milliseconds = basis::un_int(stump); 00076 // make absolutely sure we are between 0 and 999. 00077 milliseconds %= 1000; 00078 00079 astring to_return; 00080 bool did_hours = false; 00081 if (hours) { 00082 to_return += astring(astring::SPRINTF, "%uh:", hours); 00083 did_hours = true; 00084 } 00085 if (minutes || did_hours) 00086 to_return += astring(astring::SPRINTF, "%02um:", minutes); 00087 to_return += astring(astring::SPRINTF, "%02us.%03u", seconds, milliseconds); 00088 if (style == STAMP_RELATIVE) { 00089 if (past) to_return += " ago"; 00090 else to_return += " from now"; 00091 } 00092 return to_return; 00093 } 00094 00095 void time_stamp::fill_in_time() 00096 { 00097 time_representation current = get_time_now(); 00098 c_stamp = current; // reset our own time now. 00099 } 00100 00101 void time_stamp::reset(time_representation offset) 00102 { 00103 fill_in_time(); 00104 c_stamp += offset; 00105 } 00106 00107 time_stamp::time_representation time_stamp::get_time_now() 00108 { return rolling_uptime(); } 00109 00110 const double __rollover_point = 2.0 * MAXINT32; 00111 // this number is our rollover point for 32 bit integers. 00112 00113 double time_stamp::rolling_uptime() 00114 { 00115 auto_synchronizer l(__uptime_synchronizer()); 00116 // protect our rollover records. 00117 00118 static basis::un_int __last_ticks = 0; 00119 static int __rollovers = 0; 00120 00121 basis::un_int ticks_up = environment::system_uptime(); 00122 // acquire the current uptime as a 32 bit unsigned int. 00123 00124 if (ticks_up < __last_ticks) { 00125 // rollover happened. increment our tracker. 00126 __rollovers++; 00127 } 00128 __last_ticks = ticks_up; 00129 00130 return double(__rollovers) * __rollover_point + double(ticks_up); 00131 } 00132 00133 timeval time_stamp::fill_timeval_ms(int duration) 00134 { 00135 timeval time_out; // timeval has tv_sec=seconds, tv_usec=microseconds. 00136 if (!duration) { 00137 // duration is immediate for the check; just a quick poll. 00138 time_out.tv_sec = 0; 00139 time_out.tv_usec = 0; 00140 #ifdef DEBUG_PORTABLE 00141 // LOG("no duration specified"); 00142 #endif 00143 } else { 00144 // a non-zero duration means we need to compute secs and usecs. 00145 time_out.tv_sec = duration / 1000; 00146 // set the number of seconds from the input in milliseconds. 00147 duration -= time_out.tv_sec * 1000; 00148 // now take out the chunk we've already recorded as seconds. 00149 time_out.tv_usec = duration * 1000; 00150 // set the number of microseconds from the remaining milliseconds. 00151 #ifdef DEBUG_PORTABLE 00152 // LOG(isprintf("duration of %d ms went to %d sec and %d usec.", duration, 00153 // time_out.tv_sec, time_out.tv_usec)); 00154 #endif 00155 } 00156 return time_out; 00157 } 00158 00159 } //namespace. 00160
1.6.3