diff options
| author | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2022-06-20 00:00:00 +0000 |
|---|---|---|
| committer | Igor Pavlov <87184205+ip7z@users.noreply.github.com> | 2023-12-17 13:35:20 +0500 |
| commit | a3e1d227377188734b82f023f96f8e25dc40f3e6 (patch) | |
| tree | 23cad8d47eb23d26ea727b4f7f4a65124f724065 /CPP/Windows/TimeUtils.cpp | |
| parent | f19f813537c7aea1c20749c914e756b54a9c3cf5 (diff) | |
| download | 7zip-a3e1d227377188734b82f023f96f8e25dc40f3e6.tar.gz 7zip-a3e1d227377188734b82f023f96f8e25dc40f3e6.tar.bz2 7zip-a3e1d227377188734b82f023f96f8e25dc40f3e6.zip | |
22.0022.00
Diffstat (limited to 'CPP/Windows/TimeUtils.cpp')
| -rw-r--r-- | CPP/Windows/TimeUtils.cpp | 220 |
1 files changed, 195 insertions, 25 deletions
diff --git a/CPP/Windows/TimeUtils.cpp b/CPP/Windows/TimeUtils.cpp index 1f1335f..77d2c51 100644 --- a/CPP/Windows/TimeUtils.cpp +++ b/CPP/Windows/TimeUtils.cpp | |||
| @@ -22,7 +22,7 @@ static const UInt64 kUnixTimeOffset = | |||
| 22 | (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); | 22 | (UInt64)60 * 60 * 24 * (89 + 365 * (kUnixTimeStartYear - kFileTimeStartYear)); |
| 23 | static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; | 23 | static const UInt64 kNumSecondsInFileTime = (UInt64)(Int64)-1 / kNumTimeQuantumsInSecond; |
| 24 | 24 | ||
| 25 | bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw() | 25 | bool DosTime_To_FileTime(UInt32 dosTime, FILETIME &ft) throw() |
| 26 | { | 26 | { |
| 27 | #if defined(_WIN32) && !defined(UNDER_CE) | 27 | #if defined(_WIN32) && !defined(UNDER_CE) |
| 28 | return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); | 28 | return BOOLToBool(::DosDateTimeToFileTime((UInt16)(dosTime >> 16), (UInt16)(dosTime & 0xFFFF), &ft)); |
| @@ -43,7 +43,7 @@ bool DosTimeToFileTime(UInt32 dosTime, FILETIME &ft) throw() | |||
| 43 | static const UInt32 kHighDosTime = 0xFF9FBF7D; | 43 | static const UInt32 kHighDosTime = 0xFF9FBF7D; |
| 44 | static const UInt32 kLowDosTime = 0x210000; | 44 | static const UInt32 kLowDosTime = 0x210000; |
| 45 | 45 | ||
| 46 | bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() | 46 | bool FileTime_To_DosTime(const FILETIME &ft, UInt32 &dosTime) throw() |
| 47 | { | 47 | { |
| 48 | #if defined(_WIN32) && !defined(UNDER_CE) | 48 | #if defined(_WIN32) && !defined(UNDER_CE) |
| 49 | 49 | ||
| @@ -121,49 +121,86 @@ bool FileTimeToDosTime(const FILETIME &ft, UInt32 &dosTime) throw() | |||
| 121 | return true; | 121 | return true; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | UInt64 UnixTimeToFileTime64(UInt32 unixTime) throw() | 124 | |
| 125 | bool UtcFileTime_To_LocalDosTime(const FILETIME &utc, UInt32 &dosTime) throw() | ||
| 126 | { | ||
| 127 | FILETIME loc = { 0, 0 }; | ||
| 128 | const UInt64 u1 = FILETIME_To_UInt64(utc); | ||
| 129 | const UInt64 kDelta = ((UInt64)1 << 41); // it's larger than quantums in 1 sec. | ||
| 130 | if (u1 >= kDelta) | ||
| 131 | { | ||
| 132 | if (!FileTimeToLocalFileTime(&utc, &loc)) | ||
| 133 | loc = utc; | ||
| 134 | else | ||
| 135 | { | ||
| 136 | const UInt64 u2 = FILETIME_To_UInt64(loc); | ||
| 137 | const UInt64 delta = u1 < u2 ? (u2 - u1) : (u1 - u2); | ||
| 138 | if (delta > kDelta) // if FileTimeToLocalFileTime() overflow, we use UTC time | ||
| 139 | loc = utc; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | return FileTime_To_DosTime(loc, dosTime); | ||
| 143 | } | ||
| 144 | |||
| 145 | UInt64 UnixTime_To_FileTime64(UInt32 unixTime) throw() | ||
| 125 | { | 146 | { |
| 126 | return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; | 147 | return (kUnixTimeOffset + (UInt64)unixTime) * kNumTimeQuantumsInSecond; |
| 127 | } | 148 | } |
| 128 | 149 | ||
| 129 | void UnixTimeToFileTime(UInt32 unixTime, FILETIME &ft) throw() | 150 | void UnixTime_To_FileTime(UInt32 unixTime, FILETIME &ft) throw() |
| 130 | { | 151 | { |
| 131 | UInt64 v = UnixTimeToFileTime64(unixTime); | 152 | const UInt64 v = UnixTime_To_FileTime64(unixTime); |
| 132 | ft.dwLowDateTime = (DWORD)v; | 153 | ft.dwLowDateTime = (DWORD)v; |
| 133 | ft.dwHighDateTime = (DWORD)(v >> 32); | 154 | ft.dwHighDateTime = (DWORD)(v >> 32); |
| 134 | } | 155 | } |
| 135 | 156 | ||
| 136 | UInt64 UnixTime64ToFileTime64(Int64 unixTime) throw() | 157 | UInt64 UnixTime64_To_FileTime64(Int64 unixTime) throw() |
| 137 | { | 158 | { |
| 138 | return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; | 159 | return (UInt64)((Int64)kUnixTimeOffset + unixTime) * kNumTimeQuantumsInSecond; |
| 139 | } | 160 | } |
| 140 | 161 | ||
| 141 | bool UnixTime64ToFileTime(Int64 unixTime, FILETIME &ft) throw() | 162 | |
| 163 | bool UnixTime64_To_FileTime64(Int64 unixTime, UInt64 &fileTime) throw() | ||
| 142 | { | 164 | { |
| 143 | if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset)) | 165 | if (unixTime > (Int64)(kNumSecondsInFileTime - kUnixTimeOffset)) |
| 144 | { | 166 | { |
| 145 | ft.dwLowDateTime = ft.dwHighDateTime = (UInt32)(Int32)-1; | 167 | fileTime = (UInt64)(Int64)-1; |
| 146 | return false; | 168 | return false; |
| 147 | } | 169 | } |
| 148 | Int64 v = (Int64)kUnixTimeOffset + unixTime; | 170 | if (unixTime < -(Int64)kUnixTimeOffset) |
| 149 | if (v < 0) | ||
| 150 | { | 171 | { |
| 151 | ft.dwLowDateTime = ft.dwHighDateTime = 0; | 172 | fileTime = 0; |
| 152 | return false; | 173 | return false; |
| 153 | } | 174 | } |
| 154 | UInt64 v2 = (UInt64)v * kNumTimeQuantumsInSecond; | 175 | fileTime = UnixTime64_To_FileTime64(unixTime); |
| 155 | ft.dwLowDateTime = (DWORD)v2; | ||
| 156 | ft.dwHighDateTime = (DWORD)(v2 >> 32); | ||
| 157 | return true; | 176 | return true; |
| 158 | } | 177 | } |
| 159 | 178 | ||
| 160 | Int64 FileTimeToUnixTime64(const FILETIME &ft) throw() | 179 | |
| 180 | bool UnixTime64_To_FileTime(Int64 unixTime, FILETIME &ft) throw() | ||
| 161 | { | 181 | { |
| 162 | UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | 182 | UInt64 v; |
| 183 | const bool res = UnixTime64_To_FileTime64(unixTime, v); | ||
| 184 | ft.dwLowDateTime = (DWORD)v; | ||
| 185 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
| 186 | return res; | ||
| 187 | } | ||
| 188 | |||
| 189 | |||
| 190 | Int64 FileTime_To_UnixTime64(const FILETIME &ft) throw() | ||
| 191 | { | ||
| 192 | const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | ||
| 193 | return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; | ||
| 194 | } | ||
| 195 | |||
| 196 | Int64 FileTime_To_UnixTime64_and_Quantums(const FILETIME &ft, UInt32 &quantums) throw() | ||
| 197 | { | ||
| 198 | const UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | ||
| 199 | quantums = (UInt32)(winTime % kNumTimeQuantumsInSecond); | ||
| 163 | return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; | 200 | return (Int64)(winTime / kNumTimeQuantumsInSecond) - (Int64)kUnixTimeOffset; |
| 164 | } | 201 | } |
| 165 | 202 | ||
| 166 | bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw() | 203 | bool FileTime_To_UnixTime(const FILETIME &ft, UInt32 &unixTime) throw() |
| 167 | { | 204 | { |
| 168 | UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | 205 | UInt64 winTime = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; |
| 169 | winTime /= kNumTimeQuantumsInSecond; | 206 | winTime /= kNumTimeQuantumsInSecond; |
| @@ -173,9 +210,9 @@ bool FileTimeToUnixTime(const FILETIME &ft, UInt32 &unixTime) throw() | |||
| 173 | return false; | 210 | return false; |
| 174 | } | 211 | } |
| 175 | winTime -= kUnixTimeOffset; | 212 | winTime -= kUnixTimeOffset; |
| 176 | if (winTime > 0xFFFFFFFF) | 213 | if (winTime > (UInt32)0xFFFFFFFF) |
| 177 | { | 214 | { |
| 178 | unixTime = 0xFFFFFFFF; | 215 | unixTime = (UInt32)0xFFFFFFFF; |
| 179 | return false; | 216 | return false; |
| 180 | } | 217 | } |
| 181 | unixTime = (UInt32)winTime; | 218 | unixTime = (UInt32)winTime; |
| @@ -202,12 +239,13 @@ bool GetSecondsSince1601(unsigned year, unsigned month, unsigned day, | |||
| 202 | return true; | 239 | return true; |
| 203 | } | 240 | } |
| 204 | 241 | ||
| 205 | void GetCurUtcFileTime(FILETIME &ft) throw() | 242 | |
| 243 | void GetCurUtc_FiTime(CFiTime &ft) throw() | ||
| 206 | { | 244 | { |
| 245 | #ifdef _WIN32 | ||
| 246 | |||
| 207 | // Both variants provide same low resolution on WinXP: about 15 ms. | 247 | // Both variants provide same low resolution on WinXP: about 15 ms. |
| 208 | // But GetSystemTimeAsFileTime is much faster. | 248 | // But GetSystemTimeAsFileTime is much faster. |
| 209 | #ifdef _WIN32 | ||
| 210 | |||
| 211 | #ifdef UNDER_CE | 249 | #ifdef UNDER_CE |
| 212 | SYSTEMTIME st; | 250 | SYSTEMTIME st; |
| 213 | GetSystemTime(&st); | 251 | GetSystemTime(&st); |
| @@ -216,8 +254,22 @@ void GetCurUtcFileTime(FILETIME &ft) throw() | |||
| 216 | GetSystemTimeAsFileTime(&ft); | 254 | GetSystemTimeAsFileTime(&ft); |
| 217 | #endif | 255 | #endif |
| 218 | 256 | ||
| 219 | #else | 257 | #else |
| 220 | 258 | ||
| 259 | FiTime_Clear(ft); | ||
| 260 | struct timeval now; | ||
| 261 | if (gettimeofday(&now, 0 ) == 0) | ||
| 262 | { | ||
| 263 | ft.tv_sec = now.tv_sec; | ||
| 264 | ft.tv_nsec = now.tv_usec * 1000; | ||
| 265 | } | ||
| 266 | |||
| 267 | #endif | ||
| 268 | } | ||
| 269 | |||
| 270 | #ifndef _WIN32 | ||
| 271 | void GetCurUtcFileTime(FILETIME &ft) throw() | ||
| 272 | { | ||
| 221 | UInt64 v = 0; | 273 | UInt64 v = 0; |
| 222 | struct timeval now; | 274 | struct timeval now; |
| 223 | if (gettimeofday(&now, 0 ) == 0) | 275 | if (gettimeofday(&now, 0 ) == 0) |
| @@ -227,8 +279,126 @@ void GetCurUtcFileTime(FILETIME &ft) throw() | |||
| 227 | } | 279 | } |
| 228 | ft.dwLowDateTime = (DWORD)v; | 280 | ft.dwLowDateTime = (DWORD)v; |
| 229 | ft.dwHighDateTime = (DWORD)(v >> 32); | 281 | ft.dwHighDateTime = (DWORD)(v >> 32); |
| 230 | |||
| 231 | #endif | ||
| 232 | } | 282 | } |
| 283 | #endif | ||
| 284 | |||
| 233 | 285 | ||
| 234 | }} | 286 | }} |
| 287 | |||
| 288 | |||
| 289 | #ifdef _WIN32 | ||
| 290 | |||
| 291 | /* | ||
| 292 | void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec) | ||
| 293 | { | ||
| 294 | if (prec == k_PropVar_TimePrec_0 | ||
| 295 | || prec == k_PropVar_TimePrec_HighPrec | ||
| 296 | || prec >= k_PropVar_TimePrec_100ns) | ||
| 297 | return; | ||
| 298 | UInt64 v = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime; | ||
| 299 | |||
| 300 | int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base; | ||
| 301 | UInt32 d; | ||
| 302 | if (prec == k_PropVar_TimePrec_DOS) | ||
| 303 | { | ||
| 304 | // we round up as windows DosDateTimeToFileTime() | ||
| 305 | v += NWindows::NTime::kNumTimeQuantumsInSecond * 2 - 1; | ||
| 306 | d = NWindows::NTime::kNumTimeQuantumsInSecond * 2; | ||
| 307 | } | ||
| 308 | else | ||
| 309 | { | ||
| 310 | if (prec == k_PropVar_TimePrec_Unix) | ||
| 311 | numDigits = 0; | ||
| 312 | else if (numDigits < 0) | ||
| 313 | return; | ||
| 314 | d = 1; | ||
| 315 | for (unsigned k = numDigits; k < 7; k++) | ||
| 316 | d *= 10; | ||
| 317 | } | ||
| 318 | v /= d; | ||
| 319 | v *= d; | ||
| 320 | ft.dwLowDateTime = (DWORD)v; | ||
| 321 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
| 322 | } | ||
| 323 | */ | ||
| 324 | |||
| 325 | #else | ||
| 326 | |||
| 327 | /* | ||
| 328 | void FiTime_Normalize_With_Prec(CFiTime &ft, unsigned prec) | ||
| 329 | { | ||
| 330 | if (prec >= k_PropVar_TimePrec_1ns | ||
| 331 | || prec == k_PropVar_TimePrec_HighPrec) | ||
| 332 | return; | ||
| 333 | |||
| 334 | int numDigits = (int)prec - (int)k_PropVar_TimePrec_Base; | ||
| 335 | UInt32 d; | ||
| 336 | if (prec == k_PropVar_TimePrec_Unix || | ||
| 337 | prec == (int)k_PropVar_TimePrec_Base) | ||
| 338 | { | ||
| 339 | ft.tv_nsec = 0; | ||
| 340 | return; | ||
| 341 | } | ||
| 342 | if (prec == k_PropVar_TimePrec_DOS) | ||
| 343 | { | ||
| 344 | // we round up as windows DosDateTimeToFileTime() | ||
| 345 | const unsigned sec1 = (ft.tv_sec & 1); | ||
| 346 | if (ft.tv_nsec == 0 && sec1 == 0) | ||
| 347 | return; | ||
| 348 | ft.tv_nsec = 0; | ||
| 349 | ft.tv_sec += 2 - sec1; | ||
| 350 | return; | ||
| 351 | } | ||
| 352 | { | ||
| 353 | if (prec == k_PropVar_TimePrec_0 | ||
| 354 | || numDigits < 0) | ||
| 355 | numDigits = 7; | ||
| 356 | d = 1; | ||
| 357 | for (unsigned k = numDigits; k < 9; k++) | ||
| 358 | d *= 10; | ||
| 359 | ft.tv_nsec /= d; | ||
| 360 | ft.tv_nsec *= d; | ||
| 361 | } | ||
| 362 | } | ||
| 363 | */ | ||
| 364 | |||
| 365 | int Compare_FiTime(const CFiTime *a1, const CFiTime *a2) | ||
| 366 | { | ||
| 367 | if (a1->tv_sec < a2->tv_sec) return -1; | ||
| 368 | if (a1->tv_sec > a2->tv_sec) return 1; | ||
| 369 | if (a1->tv_nsec < a2->tv_nsec) return -1; | ||
| 370 | if (a1->tv_nsec > a2->tv_nsec) return 1; | ||
| 371 | return 0; | ||
| 372 | } | ||
| 373 | |||
| 374 | bool FILETIME_To_timespec(const FILETIME &ft, timespec &ts) | ||
| 375 | { | ||
| 376 | UInt32 quantums; | ||
| 377 | const Int64 sec = NWindows::NTime::FileTime_To_UnixTime64_and_Quantums(ft, quantums); | ||
| 378 | // time_t is long | ||
| 379 | const time_t sec2 = (time_t)sec; | ||
| 380 | if (sec2 == sec) | ||
| 381 | { | ||
| 382 | ts.tv_sec = sec2; | ||
| 383 | ts.tv_nsec = (long)(quantums * 100); | ||
| 384 | return true; | ||
| 385 | } | ||
| 386 | return false; | ||
| 387 | } | ||
| 388 | |||
| 389 | void FiTime_To_FILETIME_ns100(const CFiTime &ts, FILETIME &ft, unsigned &ns100) | ||
| 390 | { | ||
| 391 | const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100); | ||
| 392 | ns100 = (unsigned)((UInt64)ts.tv_nsec % 100); | ||
| 393 | ft.dwLowDateTime = (DWORD)v; | ||
| 394 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
| 395 | } | ||
| 396 | |||
| 397 | void FiTime_To_FILETIME(const CFiTime &ts, FILETIME &ft) | ||
| 398 | { | ||
| 399 | const UInt64 v = NWindows::NTime::UnixTime64_To_FileTime64(ts.tv_sec) + ((UInt64)ts.tv_nsec / 100); | ||
| 400 | ft.dwLowDateTime = (DWORD)v; | ||
| 401 | ft.dwHighDateTime = (DWORD)(v >> 32); | ||
| 402 | } | ||
| 403 | |||
| 404 | #endif | ||
