libroot: implement timegm calling the ICU backend
Change-Id: Ib4de4288e061670acbc2edea3671cee029305d33 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3748 Reviewed-by: Axel Dörfler <[email protected]>
This commit is contained in:
@@ -73,6 +73,8 @@ public:
|
||||
|
||||
virtual status_t Mktime(struct tm* inOutTm, time_t& timeOut);
|
||||
|
||||
virtual status_t Timegm(struct tm* inOutTm, time_t& timeOut);
|
||||
|
||||
private:
|
||||
const char* _QueryLocale(int category);
|
||||
const char* _SetPosixLocale(int category);
|
||||
|
||||
@@ -34,11 +34,17 @@ public:
|
||||
|
||||
status_t Mktime(struct tm* inOutTm, time_t& timeOut);
|
||||
|
||||
status_t Timegm(struct tm* inOutTm, time_t& timeOut);
|
||||
|
||||
private:
|
||||
status_t _FillTmValues(const U_NAMESPACE_QUALIFIER
|
||||
TimeZone* icuTimeZone,
|
||||
const time_t* inTime, struct tm* tmOut);
|
||||
|
||||
status_t _Mktime(const U_NAMESPACE_QUALIFIER
|
||||
TimeZone* icuTimeZone,
|
||||
struct tm* inOutTm, time_t& timeOut);
|
||||
|
||||
const ICUTimeData& fTimeData;
|
||||
|
||||
TimeConversionDataBridge* fDataBridge;
|
||||
|
||||
@@ -157,6 +157,8 @@ public:
|
||||
struct tm* tmOut) = 0;
|
||||
virtual status_t Mktime(struct tm* inOutTm, time_t& timeOut) = 0;
|
||||
|
||||
virtual status_t Timegm(struct tm* inOutTm, time_t& timeOut) = 0;
|
||||
|
||||
virtual void Initialize(LocaleDataBridge* dataBridge) = 0;
|
||||
|
||||
static status_t LoadBackend();
|
||||
|
||||
@@ -353,6 +353,15 @@ ICULocaleBackend::Mktime(struct tm* inOutTm, time_t& timeOut)
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ICULocaleBackend::Timegm(struct tm* inOutTm, time_t& timeOut)
|
||||
{
|
||||
ErrnoMaintainer errnoMaintainer;
|
||||
|
||||
return fTimeConversion.Timegm(inOutTm, timeOut);
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
ICULocaleBackend::_QueryLocale(int category)
|
||||
{
|
||||
|
||||
@@ -166,25 +166,15 @@ ICUTimeConversion::Gmtime(const time_t* inTime, struct tm* tmOut)
|
||||
status_t
|
||||
ICUTimeConversion::Mktime(struct tm* inOutTm, time_t& timeOut)
|
||||
{
|
||||
if (fTimeZone == NULL)
|
||||
return B_NO_INIT;
|
||||
return _Mktime(fTimeZone, inOutTm, timeOut);
|
||||
}
|
||||
|
||||
UErrorCode icuStatus = U_ZERO_ERROR;
|
||||
GregorianCalendar calendar(*fTimeZone, fTimeData.ICULocale(),
|
||||
icuStatus);
|
||||
if (!U_SUCCESS(icuStatus))
|
||||
return B_ERROR;
|
||||
|
||||
calendar.setLenient(TRUE);
|
||||
calendar.set(inOutTm->tm_year + 1900, inOutTm->tm_mon, inOutTm->tm_mday,
|
||||
inOutTm->tm_hour, inOutTm->tm_min, inOutTm->tm_sec);
|
||||
|
||||
UDate timeInMillis = calendar.getTime(icuStatus);
|
||||
if (!U_SUCCESS(icuStatus))
|
||||
return B_ERROR;
|
||||
timeOut = (time_t)((int64_t)timeInMillis / 1000);
|
||||
|
||||
return _FillTmValues(fTimeZone, &timeOut, inOutTm);
|
||||
status_t
|
||||
ICUTimeConversion::Timegm(struct tm* inOutTm, time_t& timeOut)
|
||||
{
|
||||
const TimeZone* icuTimeZone = TimeZone::getGMT();
|
||||
return _Mktime(icuTimeZone, inOutTm, timeOut);
|
||||
}
|
||||
|
||||
|
||||
@@ -238,5 +228,31 @@ ICUTimeConversion::_FillTmValues(const TimeZone* icuTimeZone,
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ICUTimeConversion::_Mktime(const TimeZone* icuTimeZone,
|
||||
struct tm* inOutTm, time_t& timeOut)
|
||||
{
|
||||
if (icuTimeZone == NULL)
|
||||
return B_NO_INIT;
|
||||
|
||||
UErrorCode icuStatus = U_ZERO_ERROR;
|
||||
GregorianCalendar calendar(*icuTimeZone, fTimeData.ICULocale(),
|
||||
icuStatus);
|
||||
if (!U_SUCCESS(icuStatus))
|
||||
return B_ERROR;
|
||||
|
||||
calendar.setLenient(TRUE);
|
||||
calendar.set(inOutTm->tm_year + 1900, inOutTm->tm_mon, inOutTm->tm_mday,
|
||||
inOutTm->tm_hour, inOutTm->tm_min, inOutTm->tm_sec);
|
||||
|
||||
UDate timeInMillis = calendar.getTime(icuStatus);
|
||||
if (!U_SUCCESS(icuStatus))
|
||||
return B_ERROR;
|
||||
timeOut = (time_t)((int64_t)timeInMillis / 1000);
|
||||
|
||||
return _FillTmValues(icuTimeZone, &timeOut, inOutTm);
|
||||
}
|
||||
|
||||
|
||||
} // namespace Libroot
|
||||
} // namespace BPrivate
|
||||
|
||||
@@ -33,10 +33,11 @@ long timezone = 0;
|
||||
int daylight = 0;
|
||||
|
||||
|
||||
// These two functions are used as a fallback when the locale backend could not
|
||||
// These three functions are used as a fallback when the locale backend could not
|
||||
// be loaded. They are implemented in localtime_fading_out.c.
|
||||
extern "C" struct tm* __gmtime_r_fallback(const time_t* timep, struct tm* tmp);
|
||||
extern "C" time_t __mktime_fallback(struct tm* tmp);
|
||||
extern "C" time_t __timegm_fallback(struct tm* tmp);
|
||||
|
||||
|
||||
extern "C" void
|
||||
@@ -143,3 +144,29 @@ mktime(struct tm* inTm)
|
||||
// implementation.
|
||||
return __mktime_fallback(inTm);
|
||||
}
|
||||
|
||||
|
||||
extern "C" time_t
|
||||
timegm(struct tm* inTm)
|
||||
{
|
||||
if (inTm == NULL) {
|
||||
__set_errno(EINVAL);
|
||||
return -1;
|
||||
}
|
||||
tzset();
|
||||
if (gLocaleBackend != NULL) {
|
||||
time_t timeOut;
|
||||
status_t status = gLocaleBackend->Timegm(inTm, timeOut);
|
||||
|
||||
if (status != B_OK) {
|
||||
__set_errno(EOVERFLOW);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return timeOut;
|
||||
}
|
||||
|
||||
// without a locale backend, we fall back to using a basic timegm
|
||||
// implementation.
|
||||
return __timegm_fallback(inTm);
|
||||
}
|
||||
|
||||
@@ -169,7 +169,7 @@ static int tmcomp P((const struct tm * atmp,
|
||||
*/
|
||||
struct tm* __gmtime_r_fallback(const time_t* timep, struct tm* tmp);
|
||||
time_t __mktime_fallback(struct tm* tmp);
|
||||
time_t timegm(struct tm* const tmp);
|
||||
time_t __timegm_fallback(struct tm* const tmp);
|
||||
|
||||
static struct state lclmem;
|
||||
static struct state gmtmem;
|
||||
@@ -831,10 +831,8 @@ __mktime_fallback(struct tm* tmp)
|
||||
}
|
||||
|
||||
|
||||
|
||||
time_t
|
||||
timegm(tmp)
|
||||
struct tm * const tmp;
|
||||
__timegm_fallback(struct tm* const tmp)
|
||||
{
|
||||
tmp->tm_isdst = 0;
|
||||
return time1(tmp, gmtsub, 0L);
|
||||
|
||||
Reference in New Issue
Block a user