95 // This would mostly be a call to |
95 // This would mostly be a call to |
96 // strftime(...., "%Y-%m-%d" "T" "%H:%M:%S" "%z", ....) |
96 // strftime(...., "%Y-%m-%d" "T" "%H:%M:%S" "%z", ....) |
97 // except that on Windows the %z behaves badly, so we do it ourselves. |
97 // except that on Windows the %z behaves badly, so we do it ourselves. |
98 // Also, people wanted milliseconds on there, |
98 // Also, people wanted milliseconds on there, |
99 // and strftime doesn't do milliseconds. |
99 // and strftime doesn't do milliseconds. |
100 char* os::iso8601_time(char* buffer, size_t buffer_length) { |
100 char* os::iso8601_time(char* buffer, size_t buffer_length, bool utc) { |
101 // Output will be of the form "YYYY-MM-DDThh:mm:ss.mmm+zzzz\0" |
101 // Output will be of the form "YYYY-MM-DDThh:mm:ss.mmm+zzzz\0" |
102 // 1 2 |
102 // 1 2 |
103 // 12345678901234567890123456789 |
103 // 12345678901234567890123456789 |
104 // format string: "%04d-%02d-%02dT%02d:%02d:%02d.%03d%c%02d%02d" |
104 // format string: "%04d-%02d-%02dT%02d:%02d:%02d.%03d%c%02d%02d" |
105 static const size_t needed_buffer = 29; |
105 static const size_t needed_buffer = 29; |
120 milliseconds_since_19700101 / milliseconds_per_microsecond; |
120 milliseconds_since_19700101 / milliseconds_per_microsecond; |
121 const int milliseconds_after_second = |
121 const int milliseconds_after_second = |
122 milliseconds_since_19700101 % milliseconds_per_microsecond; |
122 milliseconds_since_19700101 % milliseconds_per_microsecond; |
123 // Convert the time value to a tm and timezone variable |
123 // Convert the time value to a tm and timezone variable |
124 struct tm time_struct; |
124 struct tm time_struct; |
125 if (localtime_pd(&seconds_since_19700101, &time_struct) == NULL) { |
125 if (utc) { |
126 assert(false, "Failed localtime_pd"); |
126 if (gmtime_pd(&seconds_since_19700101, &time_struct) == NULL) { |
127 return NULL; |
127 assert(false, "Failed gmtime_pd"); |
|
128 return NULL; |
|
129 } |
|
130 } else { |
|
131 if (localtime_pd(&seconds_since_19700101, &time_struct) == NULL) { |
|
132 assert(false, "Failed localtime_pd"); |
|
133 return NULL; |
|
134 } |
128 } |
135 } |
129 #if defined(_ALLBSD_SOURCE) |
136 #if defined(_ALLBSD_SOURCE) |
130 const time_t zone = (time_t) time_struct.tm_gmtoff; |
137 const time_t zone = (time_t) time_struct.tm_gmtoff; |
131 #else |
138 #else |
132 const time_t zone = timezone; |
139 const time_t zone = timezone; |
139 const time_t seconds_per_hour = seconds_per_minute * minutes_per_hour; |
146 const time_t seconds_per_hour = seconds_per_minute * minutes_per_hour; |
140 time_t UTC_to_local = zone; |
147 time_t UTC_to_local = zone; |
141 if (time_struct.tm_isdst > 0) { |
148 if (time_struct.tm_isdst > 0) { |
142 UTC_to_local = UTC_to_local - seconds_per_hour; |
149 UTC_to_local = UTC_to_local - seconds_per_hour; |
143 } |
150 } |
|
151 |
|
152 // No offset when dealing with UTC |
|
153 if (utc) { |
|
154 UTC_to_local = 0; |
|
155 } |
|
156 |
144 // Compute the time zone offset. |
157 // Compute the time zone offset. |
145 // localtime_pd() sets timezone to the difference (in seconds) |
158 // localtime_pd() sets timezone to the difference (in seconds) |
146 // between UTC and and local time. |
159 // between UTC and and local time. |
147 // ISO 8601 says we need the difference between local time and UTC, |
160 // ISO 8601 says we need the difference between local time and UTC, |
148 // we change the sign of the localtime_pd() result. |
161 // we change the sign of the localtime_pd() result. |