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 Mktime(struct tm* inOutTm, time_t& timeOut);
|
||||||
|
|
||||||
|
virtual status_t Timegm(struct tm* inOutTm, time_t& timeOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* _QueryLocale(int category);
|
const char* _QueryLocale(int category);
|
||||||
const char* _SetPosixLocale(int category);
|
const char* _SetPosixLocale(int category);
|
||||||
|
|||||||
@@ -34,11 +34,17 @@ public:
|
|||||||
|
|
||||||
status_t Mktime(struct tm* inOutTm, time_t& timeOut);
|
status_t Mktime(struct tm* inOutTm, time_t& timeOut);
|
||||||
|
|
||||||
|
status_t Timegm(struct tm* inOutTm, time_t& timeOut);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _FillTmValues(const U_NAMESPACE_QUALIFIER
|
status_t _FillTmValues(const U_NAMESPACE_QUALIFIER
|
||||||
TimeZone* icuTimeZone,
|
TimeZone* icuTimeZone,
|
||||||
const time_t* inTime, struct tm* tmOut);
|
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;
|
const ICUTimeData& fTimeData;
|
||||||
|
|
||||||
TimeConversionDataBridge* fDataBridge;
|
TimeConversionDataBridge* fDataBridge;
|
||||||
|
|||||||
@@ -157,6 +157,8 @@ public:
|
|||||||
struct tm* tmOut) = 0;
|
struct tm* tmOut) = 0;
|
||||||
virtual status_t Mktime(struct tm* inOutTm, time_t& timeOut) = 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;
|
virtual void Initialize(LocaleDataBridge* dataBridge) = 0;
|
||||||
|
|
||||||
static status_t LoadBackend();
|
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*
|
const char*
|
||||||
ICULocaleBackend::_QueryLocale(int category)
|
ICULocaleBackend::_QueryLocale(int category)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -166,25 +166,15 @@ ICUTimeConversion::Gmtime(const time_t* inTime, struct tm* tmOut)
|
|||||||
status_t
|
status_t
|
||||||
ICUTimeConversion::Mktime(struct tm* inOutTm, time_t& timeOut)
|
ICUTimeConversion::Mktime(struct tm* inOutTm, time_t& timeOut)
|
||||||
{
|
{
|
||||||
if (fTimeZone == NULL)
|
return _Mktime(fTimeZone, inOutTm, timeOut);
|
||||||
return B_NO_INIT;
|
}
|
||||||
|
|
||||||
UErrorCode icuStatus = U_ZERO_ERROR;
|
|
||||||
GregorianCalendar calendar(*fTimeZone, fTimeData.ICULocale(),
|
|
||||||
icuStatus);
|
|
||||||
if (!U_SUCCESS(icuStatus))
|
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
calendar.setLenient(TRUE);
|
status_t
|
||||||
calendar.set(inOutTm->tm_year + 1900, inOutTm->tm_mon, inOutTm->tm_mday,
|
ICUTimeConversion::Timegm(struct tm* inOutTm, time_t& timeOut)
|
||||||
inOutTm->tm_hour, inOutTm->tm_min, inOutTm->tm_sec);
|
{
|
||||||
|
const TimeZone* icuTimeZone = TimeZone::getGMT();
|
||||||
UDate timeInMillis = calendar.getTime(icuStatus);
|
return _Mktime(icuTimeZone, inOutTm, timeOut);
|
||||||
if (!U_SUCCESS(icuStatus))
|
|
||||||
return B_ERROR;
|
|
||||||
timeOut = (time_t)((int64_t)timeInMillis / 1000);
|
|
||||||
|
|
||||||
return _FillTmValues(fTimeZone, &timeOut, inOutTm);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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 Libroot
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
@@ -33,10 +33,11 @@ long timezone = 0;
|
|||||||
int daylight = 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.
|
// 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" 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 __mktime_fallback(struct tm* tmp);
|
||||||
|
extern "C" time_t __timegm_fallback(struct tm* tmp);
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
@@ -143,3 +144,29 @@ mktime(struct tm* inTm)
|
|||||||
// implementation.
|
// implementation.
|
||||||
return __mktime_fallback(inTm);
|
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);
|
struct tm* __gmtime_r_fallback(const time_t* timep, struct tm* tmp);
|
||||||
time_t __mktime_fallback(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 lclmem;
|
||||||
static struct state gmtmem;
|
static struct state gmtmem;
|
||||||
@@ -831,10 +831,8 @@ __mktime_fallback(struct tm* tmp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
time_t
|
time_t
|
||||||
timegm(tmp)
|
__timegm_fallback(struct tm* const tmp)
|
||||||
struct tm * const tmp;
|
|
||||||
{
|
{
|
||||||
tmp->tm_isdst = 0;
|
tmp->tm_isdst = 0;
|
||||||
return time1(tmp, gmtsub, 0L);
|
return time1(tmp, gmtsub, 0L);
|
||||||
|
|||||||
Reference in New Issue
Block a user