diff options
Diffstat (limited to 'xbmc/platform/posix/XTimeUtils.cpp')
-rw-r--r-- | xbmc/platform/posix/XTimeUtils.cpp | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/xbmc/platform/posix/XTimeUtils.cpp b/xbmc/platform/posix/XTimeUtils.cpp new file mode 100644 index 0000000..e78e5cf --- /dev/null +++ b/xbmc/platform/posix/XTimeUtils.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2005-2018 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "utils/XTimeUtils.h" + +#include "PosixTimezone.h" + +#include <errno.h> +#include <mutex> +#include <time.h> + +#include <sys/times.h> + +#if defined(TARGET_ANDROID) && !defined(__LP64__) +#include <time64.h> +#endif + +#define WIN32_TIME_OFFSET ((unsigned long long)(369 * 365 + 89) * 24 * 3600 * 10000000) + +namespace KODI +{ +namespace TIME +{ + +/* + * A Leap year is any year that is divisible by four, but not by 100 unless also + * divisible by 400 + */ +#define IsLeapYear(y) ((!(y % 4)) ? (((!(y % 400)) && (y % 100)) ? 1 : 0) : 0) + +uint32_t GetTimeZoneInformation(TimeZoneInformation* timeZoneInformation) +{ + if (!timeZoneInformation) + return KODI_TIME_ZONE_ID_INVALID; + + struct tm t; + time_t tt = time(NULL); + if (localtime_r(&tt, &t)) + timeZoneInformation->bias = -t.tm_gmtoff / 60; + + timeZoneInformation->standardName = tzname[0]; + timeZoneInformation->daylightName = tzname[1]; + + return KODI_TIME_ZONE_ID_UNKNOWN; +} + +void GetLocalTime(SystemTime* systemTime) +{ + const time_t t = time(NULL); + struct tm now; + + localtime_r(&t, &now); + systemTime->year = now.tm_year + 1900; + systemTime->month = now.tm_mon + 1; + systemTime->dayOfWeek = now.tm_wday; + systemTime->day = now.tm_mday; + systemTime->hour = now.tm_hour; + systemTime->minute = now.tm_min; + systemTime->second = now.tm_sec; + systemTime->milliseconds = 0; + // NOTE: localtime_r() is not required to set this, but we Assume that it's set here. + g_timezone.m_IsDST = now.tm_isdst; +} + +int FileTimeToLocalFileTime(const FileTime* fileTime, FileTime* localFileTime) +{ + ULARGE_INTEGER l; + l.u.LowPart = fileTime->lowDateTime; + l.u.HighPart = fileTime->highDateTime; + + time_t ft; + struct tm tm_ft; + FileTimeToTimeT(fileTime, &ft); + localtime_r(&ft, &tm_ft); + + l.QuadPart += static_cast<unsigned long long>(tm_ft.tm_gmtoff) * 10000000; + + localFileTime->lowDateTime = l.u.LowPart; + localFileTime->highDateTime = l.u.HighPart; + return 1; +} + +int SystemTimeToFileTime(const SystemTime* systemTime, FileTime* fileTime) +{ + static const int dayoffset[12] = {0, 31, 59, 90, 120, 151, 182, 212, 243, 273, 304, 334}; +#if defined(TARGET_DARWIN) + static std::mutex timegm_lock; +#endif + + struct tm sysTime = {}; + sysTime.tm_year = systemTime->year - 1900; + sysTime.tm_mon = systemTime->month - 1; + sysTime.tm_wday = systemTime->dayOfWeek; + sysTime.tm_mday = systemTime->day; + sysTime.tm_hour = systemTime->hour; + sysTime.tm_min = systemTime->minute; + sysTime.tm_sec = systemTime->second; + sysTime.tm_yday = dayoffset[sysTime.tm_mon] + (sysTime.tm_mday - 1); + sysTime.tm_isdst = g_timezone.m_IsDST; + + // If this is a leap year, and we're past the 28th of Feb, increment tm_yday. + if (IsLeapYear(systemTime->year) && (sysTime.tm_yday > 58)) + sysTime.tm_yday++; + +#if defined(TARGET_DARWIN) + std::lock_guard<std::mutex> lock(timegm_lock); +#endif + +#if defined(TARGET_ANDROID) && !defined(__LP64__) + time64_t t = timegm64(&sysTime); +#else + time_t t = timegm(&sysTime); +#endif + + LARGE_INTEGER result; + result.QuadPart = (long long)t * 10000000 + (long long)systemTime->milliseconds * 10000; + result.QuadPart += WIN32_TIME_OFFSET; + + fileTime->lowDateTime = result.u.LowPart; + fileTime->highDateTime = result.u.HighPart; + + return 1; +} + +long CompareFileTime(const FileTime* fileTime1, const FileTime* fileTime2) +{ + ULARGE_INTEGER t1; + t1.u.LowPart = fileTime1->lowDateTime; + t1.u.HighPart = fileTime1->highDateTime; + + ULARGE_INTEGER t2; + t2.u.LowPart = fileTime2->lowDateTime; + t2.u.HighPart = fileTime2->highDateTime; + + if (t1.QuadPart == t2.QuadPart) + return 0; + else if (t1.QuadPart < t2.QuadPart) + return -1; + else + return 1; +} + +int FileTimeToSystemTime(const FileTime* fileTime, SystemTime* systemTime) +{ + LARGE_INTEGER file; + file.u.LowPart = fileTime->lowDateTime; + file.u.HighPart = fileTime->highDateTime; + + file.QuadPart -= WIN32_TIME_OFFSET; + file.QuadPart /= 10000; /* to milliseconds */ + systemTime->milliseconds = file.QuadPart % 1000; + file.QuadPart /= 1000; /* to seconds */ + + time_t ft = file.QuadPart; + + struct tm tm_ft; + gmtime_r(&ft, &tm_ft); + + systemTime->year = tm_ft.tm_year + 1900; + systemTime->month = tm_ft.tm_mon + 1; + systemTime->dayOfWeek = tm_ft.tm_wday; + systemTime->day = tm_ft.tm_mday; + systemTime->hour = tm_ft.tm_hour; + systemTime->minute = tm_ft.tm_min; + systemTime->second = tm_ft.tm_sec; + + return 1; +} + +int LocalFileTimeToFileTime(const FileTime* localFileTime, FileTime* fileTime) +{ + ULARGE_INTEGER l; + l.u.LowPart = localFileTime->lowDateTime; + l.u.HighPart = localFileTime->highDateTime; + + l.QuadPart += (unsigned long long) timezone * 10000000; + + fileTime->lowDateTime = l.u.LowPart; + fileTime->highDateTime = l.u.HighPart; + + return 1; +} + + +int FileTimeToTimeT(const FileTime* localFileTime, time_t* pTimeT) +{ + if (!localFileTime || !pTimeT) + return false; + + ULARGE_INTEGER fileTime; + fileTime.u.LowPart = localFileTime->lowDateTime; + fileTime.u.HighPart = localFileTime->highDateTime; + + fileTime.QuadPart -= WIN32_TIME_OFFSET; + fileTime.QuadPart /= 10000; /* to milliseconds */ + fileTime.QuadPart /= 1000; /* to seconds */ + + time_t ft = fileTime.QuadPart; + + struct tm tm_ft; + localtime_r(&ft, &tm_ft); + + *pTimeT = mktime(&tm_ft); + return 1; +} + +int TimeTToFileTime(time_t timeT, FileTime* localFileTime) +{ + if (!localFileTime) + return false; + + ULARGE_INTEGER result; + result.QuadPart = (unsigned long long) timeT * 10000000; + result.QuadPart += WIN32_TIME_OFFSET; + + localFileTime->lowDateTime = result.u.LowPart; + localFileTime->highDateTime = result.u.HighPart; + + return 1; +} + +} // namespace TIME +} // namespace KODI |