Implement tzset(), gmtime(), localtime() and mktime() on top of ICU
* no longer keep a separate time-backend, since the implementation needs to access (data of) the locale backend anyway * moved more stuff from localtime_fading_out.c to localtime.cpp * added respective tests to locale_test * added two more tests copied from glibc, test_time.c and tst-mktime.c git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38162 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -16,6 +16,7 @@
|
|||||||
#include "ICUMessagesData.h"
|
#include "ICUMessagesData.h"
|
||||||
#include "ICUMonetaryData.h"
|
#include "ICUMonetaryData.h"
|
||||||
#include "ICUNumericData.h"
|
#include "ICUNumericData.h"
|
||||||
|
#include "ICUTimeConversion.h"
|
||||||
#include "ICUTimeData.h"
|
#include "ICUTimeData.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -44,6 +45,13 @@ public:
|
|||||||
virtual status_t Strxfrm(char* out, const char* in, size_t size,
|
virtual status_t Strxfrm(char* out, const char* in, size_t size,
|
||||||
size_t& outSize);
|
size_t& outSize);
|
||||||
|
|
||||||
|
virtual status_t TZSet(const char* timeZoneID);
|
||||||
|
virtual status_t Localtime(const time_t* inTime,
|
||||||
|
struct tm* tmOut);
|
||||||
|
virtual status_t Gmtime(const time_t* inTime, struct tm* tmOut);
|
||||||
|
|
||||||
|
virtual status_t Mktime(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);
|
||||||
@@ -62,6 +70,7 @@ private:
|
|||||||
ICUMonetaryData fMonetaryData;
|
ICUMonetaryData fMonetaryData;
|
||||||
ICUNumericData fNumericData;
|
ICUNumericData fNumericData;
|
||||||
ICUTimeData fTimeData;
|
ICUTimeData fTimeData;
|
||||||
|
ICUTimeConversion fTimeConversion;
|
||||||
|
|
||||||
// static posix langinfo data
|
// static posix langinfo data
|
||||||
const char** fPosixLanginfo;
|
const char** fPosixLanginfo;
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Oliver Tappe, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _ICU_TIME_CONVERSION_H
|
||||||
|
#define _ICU_TIME_CONVERSION_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "ICUTimeData.h"
|
||||||
|
#include "LocaleBackend.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
|
||||||
|
class ICUTimeConversion {
|
||||||
|
public:
|
||||||
|
ICUTimeConversion(const ICUTimeData& timeData);
|
||||||
|
virtual ~ICUTimeConversion();
|
||||||
|
|
||||||
|
virtual void Initialize(
|
||||||
|
TimeConversionDataBridge* dataBridge);
|
||||||
|
|
||||||
|
status_t TZSet(const char* timeZoneID);
|
||||||
|
|
||||||
|
status_t Localtime(const time_t* inTime,
|
||||||
|
struct tm* tmOut);
|
||||||
|
status_t Gmtime(const time_t* inTime, struct tm* tmOut);
|
||||||
|
|
||||||
|
status_t Mktime(struct tm* inOutTm, time_t& timeOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _FillTmValues(const TimeZone* icuTimeZone,
|
||||||
|
const time_t* inTime, struct tm* tmOut);
|
||||||
|
|
||||||
|
const ICUTimeData& fTimeData;
|
||||||
|
|
||||||
|
TimeConversionDataBridge* fDataBridge;
|
||||||
|
|
||||||
|
char fTimeZoneID[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _ICU_TIME_BACKEND_H
|
||||||
@@ -21,6 +21,7 @@ class ICUTimeData : public ICUCategoryData {
|
|||||||
typedef ICUCategoryData inherited;
|
typedef ICUCategoryData inherited;
|
||||||
public:
|
public:
|
||||||
ICUTimeData(struct lc_time_t& lcTimeInfo);
|
ICUTimeData(struct lc_time_t& lcTimeInfo);
|
||||||
|
~ICUTimeData();
|
||||||
|
|
||||||
void Initialize(LocaleTimeDataBridge* dataBridge);
|
void Initialize(LocaleTimeDataBridge* dataBridge);
|
||||||
|
|
||||||
@@ -30,6 +31,8 @@ public:
|
|||||||
|
|
||||||
const char* GetLanginfo(int index);
|
const char* GetLanginfo(int index);
|
||||||
|
|
||||||
|
const Locale& ICULocale() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
status_t _SetLCTimeEntries(const UnicodeString* strings,
|
status_t _SetLCTimeEntries(const UnicodeString* strings,
|
||||||
char* destination, int entrySize,
|
char* destination, int entrySize,
|
||||||
@@ -52,7 +55,8 @@ private:
|
|||||||
char fAmPmFormat[32];
|
char fAmPmFormat[32];
|
||||||
|
|
||||||
struct lc_time_t& fLCTimeInfo;
|
struct lc_time_t& fLCTimeInfo;
|
||||||
const struct lc_time_t* fPosixLCTimeInfo;
|
|
||||||
|
LocaleTimeDataBridge* fDataBridge;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <SupportDefs.h>
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
#include <wctype.h>
|
#include <wctype.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -64,12 +65,22 @@ struct LocaleTimeDataBridge {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct TimeConversionDataBridge {
|
||||||
|
int* addrOfDaylight;
|
||||||
|
long* addrOfTimezone;
|
||||||
|
char** addrOfTZName;
|
||||||
|
|
||||||
|
TimeConversionDataBridge();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct LocaleDataBridge {
|
struct LocaleDataBridge {
|
||||||
LocaleCtypeDataBridge ctypeDataBridge;
|
LocaleCtypeDataBridge ctypeDataBridge;
|
||||||
LocaleMessagesDataBridge messagesDataBridge;
|
LocaleMessagesDataBridge messagesDataBridge;
|
||||||
LocaleMonetaryDataBridge monetaryDataBridge;
|
LocaleMonetaryDataBridge monetaryDataBridge;
|
||||||
LocaleNumericDataBridge numericDataBridge;
|
LocaleNumericDataBridge numericDataBridge;
|
||||||
LocaleTimeDataBridge timeDataBridge;
|
LocaleTimeDataBridge timeDataBridge;
|
||||||
|
TimeConversionDataBridge timeConversionDataBridge;
|
||||||
const char** posixLanginfo;
|
const char** posixLanginfo;
|
||||||
|
|
||||||
LocaleDataBridge();
|
LocaleDataBridge();
|
||||||
@@ -96,6 +107,13 @@ public:
|
|||||||
virtual status_t Strxfrm(char* out, const char* in, size_t size,
|
virtual status_t Strxfrm(char* out, const char* in, size_t size,
|
||||||
size_t& outSize) = 0;
|
size_t& outSize) = 0;
|
||||||
|
|
||||||
|
virtual status_t TZSet(const char* timeZoneID) = 0;
|
||||||
|
virtual status_t Localtime(const time_t* inTime,
|
||||||
|
struct tm* tmOut) = 0;
|
||||||
|
virtual status_t Gmtime(const time_t* inTime,
|
||||||
|
struct tm* tmOut) = 0;
|
||||||
|
virtual status_t Mktime(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();
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, Oliver Tappe, [email protected].
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef _ICU_TIME_BACKEND_H
|
|
||||||
#define _ICU_TIME_BACKEND_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <TimeBackend.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
|
|
||||||
|
|
||||||
class ICUTimeBackend : public TimeBackend {
|
|
||||||
public:
|
|
||||||
ICUTimeBackend();
|
|
||||||
virtual ~ICUTimeBackend();
|
|
||||||
|
|
||||||
virtual const status_t TZSet();
|
|
||||||
|
|
||||||
virtual void Initialize(TimeDataBridge* dataBridge);
|
|
||||||
|
|
||||||
private:
|
|
||||||
TimeDataBridge fDataBridge;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPrivate
|
|
||||||
|
|
||||||
|
|
||||||
#endif // _ICU_TIME_BACKEND_H
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, Oliver Tappe, [email protected].
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef _TIME_BACKEND_H
|
|
||||||
#define _TIME_BACKEND_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
|
|
||||||
|
|
||||||
struct TimeDataBridge {
|
|
||||||
int* addrOfDaylight;
|
|
||||||
long* addrOfTimezone;
|
|
||||||
char** addrOfTZName;
|
|
||||||
|
|
||||||
TimeDataBridge();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class TimeBackend {
|
|
||||||
public:
|
|
||||||
TimeBackend();
|
|
||||||
virtual ~TimeBackend();
|
|
||||||
|
|
||||||
virtual const status_t TZSet() = 0;
|
|
||||||
|
|
||||||
virtual void Initialize(TimeDataBridge* dataBridge) = 0;
|
|
||||||
|
|
||||||
static status_t LoadBackend();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
extern TimeBackend* gTimeBackend;
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPrivate
|
|
||||||
|
|
||||||
|
|
||||||
#endif // _TIME_BACKEND_H
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, Oliver Tappe, [email protected].
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
#ifndef _LOCALTIME_H
|
|
||||||
#define _LOCALTIME_H
|
|
||||||
|
|
||||||
|
|
||||||
#include <SupportDefs.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
|
|
||||||
|
|
||||||
static const char* skPosixTimeZoneInfoFile = "libroot_timezone_info";
|
|
||||||
static const int skTimeZoneInfoNameMax = 32;
|
|
||||||
|
|
||||||
// holds persistent info set by Time preflet
|
|
||||||
struct time_zone_info {
|
|
||||||
char short_std_name[skTimeZoneInfoNameMax];
|
|
||||||
char short_dst_name[skTimeZoneInfoNameMax];
|
|
||||||
uint32 offset_from_gmt;
|
|
||||||
bool uses_daylight_saving;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPrivate
|
|
||||||
|
|
||||||
|
|
||||||
#endif // _LOCALTIME_H
|
|
||||||
+39
-1
@@ -29,7 +29,8 @@ ICULocaleBackend::ICULocaleBackend()
|
|||||||
:
|
:
|
||||||
fMonetaryData(fLocaleConv),
|
fMonetaryData(fLocaleConv),
|
||||||
fNumericData(fLocaleConv),
|
fNumericData(fLocaleConv),
|
||||||
fTimeData(fLCTimeInfo)
|
fTimeData(fLCTimeInfo),
|
||||||
|
fTimeConversion(fTimeData)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@ ICULocaleBackend::Initialize(LocaleDataBridge* dataBridge)
|
|||||||
fMonetaryData.Initialize(&dataBridge->monetaryDataBridge);
|
fMonetaryData.Initialize(&dataBridge->monetaryDataBridge);
|
||||||
fNumericData.Initialize(&dataBridge->numericDataBridge);
|
fNumericData.Initialize(&dataBridge->numericDataBridge);
|
||||||
fTimeData.Initialize(&dataBridge->timeDataBridge);
|
fTimeData.Initialize(&dataBridge->timeDataBridge);
|
||||||
|
fTimeConversion.Initialize(&dataBridge->timeConversionDataBridge);
|
||||||
|
|
||||||
fPosixLanginfo = dataBridge->posixLanginfo;
|
fPosixLanginfo = dataBridge->posixLanginfo;
|
||||||
|
|
||||||
@@ -242,6 +244,42 @@ ICULocaleBackend::Strxfrm(char* out, const char* in, size_t size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ICULocaleBackend::TZSet(const char* timeZoneID)
|
||||||
|
{
|
||||||
|
ErrnoMaintainer errnoMaintainer;
|
||||||
|
|
||||||
|
return fTimeConversion.TZSet(timeZoneID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ICULocaleBackend::Localtime(const time_t* inTime, struct tm* tmOut)
|
||||||
|
{
|
||||||
|
ErrnoMaintainer errnoMaintainer;
|
||||||
|
|
||||||
|
return fTimeConversion.Localtime(inTime, tmOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ICULocaleBackend::Gmtime(const time_t* inTime, struct tm* tmOut)
|
||||||
|
{
|
||||||
|
ErrnoMaintainer errnoMaintainer;
|
||||||
|
|
||||||
|
return fTimeConversion.Gmtime(inTime, tmOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ICULocaleBackend::Mktime(struct tm* inOutTm, time_t& timeOut)
|
||||||
|
{
|
||||||
|
ErrnoMaintainer errnoMaintainer;
|
||||||
|
|
||||||
|
return fTimeConversion.Mktime(inOutTm, timeOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
ICULocaleBackend::_QueryLocale(int category)
|
ICULocaleBackend::_QueryLocale(int category)
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010, Oliver Tappe, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "ICUTimeConversion.h"
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
#include <unicode/gregocal.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace BPrivate {
|
||||||
|
|
||||||
|
|
||||||
|
ICUTimeConversion::ICUTimeConversion(const ICUTimeData& timeData)
|
||||||
|
:
|
||||||
|
fTimeData(timeData),
|
||||||
|
fDataBridge(NULL)
|
||||||
|
{
|
||||||
|
fTimeZoneID[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ICUTimeConversion::~ICUTimeConversion()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ICUTimeConversion::Initialize(TimeConversionDataBridge* dataBridge)
|
||||||
|
{
|
||||||
|
fDataBridge = dataBridge;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ICUTimeConversion::TZSet(const char* timeZoneID)
|
||||||
|
{
|
||||||
|
// nothing to do if the given name matches any name of the current timezone
|
||||||
|
if (strcasecmp(fTimeZoneID, timeZoneID) == 0)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
strlcpy(fTimeZoneID, timeZoneID, sizeof(fTimeZoneID));
|
||||||
|
|
||||||
|
ObjectDeleter<TimeZone> icuTimeZone = TimeZone::createTimeZone(fTimeZoneID);
|
||||||
|
if (icuTimeZone.Get() == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
int32_t rawOffset;
|
||||||
|
int32_t dstOffset;
|
||||||
|
UDate nowMillis = 1000 * (UDate)time(NULL);
|
||||||
|
UErrorCode icuStatus = U_ZERO_ERROR;
|
||||||
|
icuTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus)) {
|
||||||
|
*fDataBridge->addrOfTimezone = 0;
|
||||||
|
*fDataBridge->addrOfDaylight = false;
|
||||||
|
strcpy(fDataBridge->addrOfTZName[0], "GMT");
|
||||||
|
strcpy(fDataBridge->addrOfTZName[1], "GMT");
|
||||||
|
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*fDataBridge->addrOfTimezone = (rawOffset + dstOffset) / 1000;
|
||||||
|
// we want seconds, not ms (which ICU gives us)
|
||||||
|
|
||||||
|
*fDataBridge->addrOfDaylight = icuTimeZone->useDaylightTime();
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
UnicodeString icuString;
|
||||||
|
icuTimeZone->getDisplayName(i == 1, TimeZone::SHORT_COMMONLY_USED,
|
||||||
|
fTimeData.ICULocale(), icuString);
|
||||||
|
CheckedArrayByteSink byteSink(fDataBridge->addrOfTZName[i],
|
||||||
|
sizeof(fTimeZoneID));
|
||||||
|
icuString.toUTF8(byteSink);
|
||||||
|
|
||||||
|
// make sure to canonicalize "GMT+00:00" to just "GMT"
|
||||||
|
if (strcmp(fDataBridge->addrOfTZName[i], "GMT+00:00") == 0)
|
||||||
|
fDataBridge->addrOfTZName[i][3] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ICUTimeConversion::Localtime(const time_t* inTime, struct tm* tmOut)
|
||||||
|
{
|
||||||
|
ObjectDeleter<TimeZone> icuTimeZone = TimeZone::createTimeZone(fTimeZoneID);
|
||||||
|
if (icuTimeZone.Get() == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
tmOut->tm_zone = fTimeZoneID;
|
||||||
|
return _FillTmValues(icuTimeZone.Get(), inTime, tmOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ICUTimeConversion::Gmtime(const time_t* inTime, struct tm* tmOut)
|
||||||
|
{
|
||||||
|
const TimeZone* icuTimeZone = TimeZone::getGMT();
|
||||||
|
// no delete - doesn't belong to us
|
||||||
|
|
||||||
|
return _FillTmValues(icuTimeZone, inTime, tmOut);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ICUTimeConversion::Mktime(struct tm* inOutTm, time_t& timeOut)
|
||||||
|
{
|
||||||
|
ObjectDeleter<TimeZone> icuTimeZone = TimeZone::createTimeZone(fTimeZoneID);
|
||||||
|
if (icuTimeZone.Get() == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
UErrorCode icuStatus = U_ZERO_ERROR;
|
||||||
|
GregorianCalendar calendar(*icuTimeZone.Get(), 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.Get(), &timeOut, inOutTm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ICUTimeConversion::_FillTmValues(const TimeZone* icuTimeZone,
|
||||||
|
const time_t* inTime, struct tm* tmOut)
|
||||||
|
{
|
||||||
|
UErrorCode icuStatus = U_ZERO_ERROR;
|
||||||
|
GregorianCalendar calendar(*icuTimeZone, fTimeData.ICULocale(), icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
calendar.setTime(1000 * (UDate)*inTime, icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
tmOut->tm_sec = calendar.get(UCAL_SECOND, icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
tmOut->tm_min = calendar.get(UCAL_MINUTE, icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
tmOut->tm_hour = calendar.get(UCAL_HOUR_OF_DAY, icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
tmOut->tm_mday = calendar.get(UCAL_DAY_OF_MONTH, icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
tmOut->tm_mon = calendar.get(UCAL_MONTH, icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
tmOut->tm_year = calendar.get(UCAL_YEAR, icuStatus) - 1900;
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
tmOut->tm_wday = calendar.get(UCAL_DAY_OF_WEEK, icuStatus) - 1;
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
tmOut->tm_yday = calendar.get(UCAL_DAY_OF_YEAR, icuStatus) - 1;
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
tmOut->tm_isdst = calendar.inDaylightTime(icuStatus);
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
tmOut->tm_gmtoff = (calendar.get(UCAL_ZONE_OFFSET, icuStatus)
|
||||||
|
+ calendar.get(UCAL_DST_OFFSET, icuStatus)) / 1000;
|
||||||
|
if (!U_SUCCESS(icuStatus))
|
||||||
|
return B_ERROR;
|
||||||
|
tmOut->tm_zone = fDataBridge->addrOfTZName[tmOut->tm_isdst ? 1 : 0];
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace BPrivate
|
||||||
+32
-16
@@ -10,8 +10,11 @@
|
|||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
|
|
||||||
#include <unicode/dtfmtsym.h>
|
#include <unicode/dtfmtsym.h>
|
||||||
|
#include <unicode/gregocal.h>
|
||||||
#include <unicode/smpdtfmt.h>
|
#include <unicode/smpdtfmt.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
|
|
||||||
@@ -19,7 +22,7 @@ namespace BPrivate {
|
|||||||
ICUTimeData::ICUTimeData(struct lc_time_t& lcTimeInfo)
|
ICUTimeData::ICUTimeData(struct lc_time_t& lcTimeInfo)
|
||||||
:
|
:
|
||||||
fLCTimeInfo(lcTimeInfo),
|
fLCTimeInfo(lcTimeInfo),
|
||||||
fPosixLCTimeInfo(NULL)
|
fDataBridge(NULL)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < 12; ++i) {
|
for (int i = 0; i < 12; ++i) {
|
||||||
fLCTimeInfo.mon[i] = fMon[i];
|
fLCTimeInfo.mon[i] = fMon[i];
|
||||||
@@ -41,10 +44,15 @@ ICUTimeData::ICUTimeData(struct lc_time_t& lcTimeInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ICUTimeData::~ICUTimeData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ICUTimeData::Initialize(LocaleTimeDataBridge* dataBridge)
|
ICUTimeData::Initialize(LocaleTimeDataBridge* dataBridge)
|
||||||
{
|
{
|
||||||
fPosixLCTimeInfo = dataBridge->posixLCTimeInfo;
|
fDataBridge = dataBridge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -140,7 +148,7 @@ ICUTimeData::SetTo(const Locale& locale, const char* posixLocaleName)
|
|||||||
count, 12);
|
count, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(fAmPmFormat, fPosixLCTimeInfo->ampm_fmt);
|
strcpy(fAmPmFormat, fDataBridge->posixLCTimeInfo->ampm_fmt);
|
||||||
// ICU does not provide anything for this (and that makes sense, too)
|
// ICU does not provide anything for this (and that makes sense, too)
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -154,22 +162,22 @@ ICUTimeData::SetToPosix()
|
|||||||
|
|
||||||
if (result == B_OK) {
|
if (result == B_OK) {
|
||||||
for (int i = 0; i < 12; ++i) {
|
for (int i = 0; i < 12; ++i) {
|
||||||
strcpy(fMon[i], fPosixLCTimeInfo->mon[i]);
|
strcpy(fMon[i], fDataBridge->posixLCTimeInfo->mon[i]);
|
||||||
strcpy(fMonth[i], fPosixLCTimeInfo->month[i]);
|
strcpy(fMonth[i], fDataBridge->posixLCTimeInfo->month[i]);
|
||||||
strcpy(fAltMonth[i], fPosixLCTimeInfo->alt_month[i]);
|
strcpy(fAltMonth[i], fDataBridge->posixLCTimeInfo->alt_month[i]);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 7; ++i) {
|
for (int i = 0; i < 7; ++i) {
|
||||||
strcpy(fWday[i], fPosixLCTimeInfo->wday[i]);
|
strcpy(fWday[i], fDataBridge->posixLCTimeInfo->wday[i]);
|
||||||
strcpy(fWeekday[i], fPosixLCTimeInfo->weekday[i]);
|
strcpy(fWeekday[i], fDataBridge->posixLCTimeInfo->weekday[i]);
|
||||||
}
|
}
|
||||||
strcpy(fTimeFormat, fPosixLCTimeInfo->X_fmt);
|
strcpy(fTimeFormat, fDataBridge->posixLCTimeInfo->X_fmt);
|
||||||
strcpy(fDateFormat, fPosixLCTimeInfo->x_fmt);
|
strcpy(fDateFormat, fDataBridge->posixLCTimeInfo->x_fmt);
|
||||||
strcpy(fDateTimeFormat, fPosixLCTimeInfo->c_fmt);
|
strcpy(fDateTimeFormat, fDataBridge->posixLCTimeInfo->c_fmt);
|
||||||
strcpy(fAm, fPosixLCTimeInfo->am);
|
strcpy(fAm, fDataBridge->posixLCTimeInfo->am);
|
||||||
strcpy(fPm, fPosixLCTimeInfo->pm);
|
strcpy(fPm, fDataBridge->posixLCTimeInfo->pm);
|
||||||
strcpy(fDateTimeZoneFormat, fPosixLCTimeInfo->date_fmt);
|
strcpy(fDateTimeZoneFormat, fDataBridge->posixLCTimeInfo->date_fmt);
|
||||||
strcpy(fMonthDayOrder, fPosixLCTimeInfo->md_order);
|
strcpy(fMonthDayOrder, fDataBridge->posixLCTimeInfo->md_order);
|
||||||
strcpy(fAmPmFormat, fPosixLCTimeInfo->ampm_fmt);
|
strcpy(fAmPmFormat, fDataBridge->posixLCTimeInfo->ampm_fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -397,4 +405,12 @@ ICUTimeData::_SetLCTimePattern(DateFormat* format, char* destination,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Locale&
|
||||||
|
ICUTimeData::ICULocale() const
|
||||||
|
{
|
||||||
|
return fLocale;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
@@ -1,14 +1,33 @@
|
|||||||
SubDir HAIKU_TOP src system libroot add-ons icu ;
|
SubDir HAIKU_TOP src system libroot add-ons icu ;
|
||||||
|
|
||||||
local addonIcuObjects =
|
UsePrivateHeaders
|
||||||
addon_icu_locale.o
|
libroot
|
||||||
|
[ FDirName libroot locale ]
|
||||||
|
[ FDirName libroot time ]
|
||||||
|
shared
|
||||||
;
|
;
|
||||||
|
|
||||||
|
local sources =
|
||||||
|
ICUCategoryData.cpp
|
||||||
|
ICUCollateData.cpp
|
||||||
|
ICUCtypeData.cpp
|
||||||
|
ICULocaleBackend.cpp
|
||||||
|
ICULocaleconvData.cpp
|
||||||
|
ICUMessagesData.cpp
|
||||||
|
ICUMonetaryData.cpp
|
||||||
|
ICUNumericData.cpp
|
||||||
|
ICUTimeConversion.cpp
|
||||||
|
ICUTimeData.cpp
|
||||||
|
;
|
||||||
|
|
||||||
|
SubDirSysHdrs $(HAIKU_ICU_HEADERS) ;
|
||||||
|
Includes [ FGristFiles $(sources) ] : $(HAIKU_ICU_HEADERS_DEPENDENCY) ;
|
||||||
|
# Dependency needed to trigger downloading/unzipping the package before
|
||||||
|
# compiling the files.
|
||||||
|
|
||||||
SharedLibrary libroot-addon-icu.so
|
SharedLibrary libroot-addon-icu.so
|
||||||
|
: $(sources)
|
||||||
:
|
:
|
||||||
:
|
|
||||||
$(addonIcuObjects:G=nogrist)
|
|
||||||
$(TARGET_LIBSTDC++) $(HAIKU_ICU_LIBS)
|
$(TARGET_LIBSTDC++) $(HAIKU_ICU_LIBS)
|
||||||
;
|
;
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src system libroot add-ons icu locale ;
|
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src system libroot add-ons icu locale ;
|
|
||||||
|
|
||||||
UsePrivateHeaders
|
|
||||||
libroot
|
|
||||||
[ FDirName libroot locale ]
|
|
||||||
[ FDirName libroot time ]
|
|
||||||
;
|
|
||||||
|
|
||||||
local sources =
|
|
||||||
ICUCategoryData.cpp
|
|
||||||
ICUCollateData.cpp
|
|
||||||
ICUCtypeData.cpp
|
|
||||||
ICULocaleBackend.cpp
|
|
||||||
ICULocaleconvData.cpp
|
|
||||||
ICUMessagesData.cpp
|
|
||||||
ICUMonetaryData.cpp
|
|
||||||
ICUNumericData.cpp
|
|
||||||
ICUTimeData.cpp
|
|
||||||
;
|
|
||||||
|
|
||||||
SubDirSysHdrs $(HAIKU_ICU_HEADERS) ;
|
|
||||||
Includes [ FGristFiles $(sources) ] : $(HAIKU_ICU_HEADERS_DEPENDENCY) ;
|
|
||||||
# Dependency needed to trigger downloading/unzipping the package before
|
|
||||||
# compiling the files.
|
|
||||||
|
|
||||||
MergeObject addon_icu_locale.o : $(sources) ;
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, Oliver Tappe, [email protected].
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "ICUTimeBackend.h"
|
|
||||||
|
|
||||||
#include <new>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include <unicode/timezone.h>
|
|
||||||
|
|
||||||
#include <ErrnoMaintainer.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" TimeBackend*
|
|
||||||
CreateInstance()
|
|
||||||
{
|
|
||||||
return new(std::nothrow) ICUTimeBackend();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ICUTimeBackend::ICUTimeBackend()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ICUTimeBackend::~ICUTimeBackend()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ICUTimeBackend::Initialize(TimeDataBridge* dataBridge)
|
|
||||||
{
|
|
||||||
fDataBridge = dataBridge;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ICUTimeBackend::TZSet(void)
|
|
||||||
{
|
|
||||||
ErrnoMaintainer errnoMaintainer;
|
|
||||||
|
|
||||||
TimeZone* icuTimeZone;
|
|
||||||
if (zoneCode == NULL || zoneCode[0] == '\0')
|
|
||||||
icuTimeZone = TimeZone::createDefault();
|
|
||||||
else
|
|
||||||
icuTimeZone = TimeZone::createTimeZone(zoneCode);
|
|
||||||
|
|
||||||
UnicodeString unicodeString;
|
|
||||||
icuTimeZone->getID(unicodeString);
|
|
||||||
BStringByteSink converter(&fCode);
|
|
||||||
unicodeString.toUTF8(converter);
|
|
||||||
|
|
||||||
unicodeString.remove();
|
|
||||||
icuTimeZone->getDisplayName(unicodeString);
|
|
||||||
converter.SetTo(&fName);
|
|
||||||
unicodeString.toUTF8(converter);
|
|
||||||
|
|
||||||
int32_t rawOffset;
|
|
||||||
int32_t dstOffset;
|
|
||||||
UDate nowMillis = 1000 * (double)time(NULL);
|
|
||||||
|
|
||||||
UErrorCode error = U_ZERO_ERROR;
|
|
||||||
icuTimeZone->getOffset(nowMillis, FALSE, rawOffset, dstOffset, error);
|
|
||||||
if (!U_SUCCESS(error)) {
|
|
||||||
fOffsetFromGMT = 0;
|
|
||||||
fInitStatus = B_ERROR;
|
|
||||||
} else {
|
|
||||||
fOffsetFromGMT = (rawOffset + dstOffset) / 1000;
|
|
||||||
// we want seconds, not ms (which ICU gives us)
|
|
||||||
fInitStatus = B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete icuTimeZone;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPrivate
|
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
SubDir HAIKU_TOP src system libroot posix locale ;
|
SubDir HAIKU_TOP src system libroot posix locale ;
|
||||||
|
|
||||||
UsePrivateHeaders [ FDirName libroot locale ] ;
|
UsePrivateHeaders
|
||||||
UsePrivateHeaders [ FDirName libroot time ] ;
|
[ FDirName libroot locale ]
|
||||||
|
[ FDirName libroot time ]
|
||||||
|
;
|
||||||
|
|
||||||
MergeObject posix_locale.o :
|
MergeObject posix_locale.o :
|
||||||
ctype.cpp
|
ctype.cpp
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <langinfo.h>
|
#include <langinfo.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <PosixCtype.h>
|
#include <PosixCtype.h>
|
||||||
#include <PosixLanginfo.h>
|
#include <PosixLanginfo.h>
|
||||||
@@ -85,6 +86,15 @@ LocaleTimeDataBridge::LocaleTimeDataBridge()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TimeConversionDataBridge::TimeConversionDataBridge()
|
||||||
|
:
|
||||||
|
addrOfDaylight(&daylight),
|
||||||
|
addrOfTimezone(&timezone),
|
||||||
|
addrOfTZName(tzname)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
LocaleDataBridge::LocaleDataBridge()
|
LocaleDataBridge::LocaleDataBridge()
|
||||||
:
|
:
|
||||||
posixLanginfo(gPosixLanginfo)
|
posixLanginfo(gPosixLanginfo)
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ SubDir HAIKU_TOP src system libroot posix time ;
|
|||||||
SubDirCcFlags -DNOID -DTZDIR='get_timezones_directory()' -DUSG_COMPAT
|
SubDirCcFlags -DNOID -DTZDIR='get_timezones_directory()' -DUSG_COMPAT
|
||||||
-DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone -DPCTS=1 -DSTD_INSPIRED ;
|
-DTM_GMTOFF=tm_gmtoff -DTM_ZONE=tm_zone -DPCTS=1 -DSTD_INSPIRED ;
|
||||||
|
|
||||||
UsePrivateHeaders [ FDirName libroot locale ] ;
|
UsePrivateHeaders
|
||||||
UsePrivateHeaders [ FDirName libroot time ] ;
|
[ FDirName libroot locale ]
|
||||||
|
[ FDirName libroot time ]
|
||||||
|
;
|
||||||
UsePrivateSystemHeaders ;
|
UsePrivateSystemHeaders ;
|
||||||
|
|
||||||
MergeObject posix_time.o :
|
MergeObject posix_time.o :
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, Oliver Tappe, [email protected].
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "TimeBackend.h"
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
|
|
||||||
|
|
||||||
TimeBackend* gTimeBackend = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
static TimeDataBridge sTimeDataBridge;
|
|
||||||
static pthread_once_t sBackendInitOnce = PTHREAD_ONCE_INIT;
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
LoadBackend()
|
|
||||||
{
|
|
||||||
void* imageHandle = dlopen("libroot-addon-icu.so", RTLD_LAZY);
|
|
||||||
if (imageHandle == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
typedef TimeBackend* (*symbolType)();
|
|
||||||
symbolType createInstanceFunc
|
|
||||||
= (symbolType)dlsym(imageHandle, "CreateInstance");
|
|
||||||
if (createInstanceFunc == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
gTimeBackend = createInstanceFunc();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TimeBackend::TimeBackend()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TimeBackend::~TimeBackend()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
TimeBackend::LoadBackend()
|
|
||||||
{
|
|
||||||
if (gTimeBackend == NULL) {
|
|
||||||
pthread_once(&sBackendInitOnce, &BPrivate::LoadBackend);
|
|
||||||
if (gTimeBackend != NULL)
|
|
||||||
gTimeBackend->Initialize(&sTimeDataBridge);
|
|
||||||
}
|
|
||||||
|
|
||||||
return gTimeBackend != NULL ? B_OK : B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPrivate
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010, Oliver Tappe, [email protected].
|
|
||||||
* Distributed under the terms of the MIT License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "TimeBackend.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
|
|
||||||
|
|
||||||
TimeDataBridge::TimeDataBridge()
|
|
||||||
:
|
|
||||||
addrOfDaylight(&daylight),
|
|
||||||
addrOfTimezone(&timezone),
|
|
||||||
addrOfTZName(tzname)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPrivate
|
|
||||||
@@ -4,51 +4,153 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
#include <localtime.h>
|
|
||||||
|
|
||||||
#include <FindDirectory.h>
|
#include <FindDirectory.h>
|
||||||
#include <StorageDefs.h>
|
#include <StorageDefs.h>
|
||||||
|
|
||||||
|
#include "LocaleBackend.h"
|
||||||
|
|
||||||
char* tzname[2] = { "???", "???" };
|
|
||||||
|
using BPrivate::gLocaleBackend;
|
||||||
|
using BPrivate::LocaleBackend;
|
||||||
|
|
||||||
|
|
||||||
|
static char sStandardTZName[64] = { "???" };
|
||||||
|
static char sDaylightSavingTZName[64] = { "???" };
|
||||||
|
|
||||||
|
|
||||||
|
char* tzname[2] = {
|
||||||
|
sStandardTZName,
|
||||||
|
sDaylightSavingTZName
|
||||||
|
};
|
||||||
long timezone = 0;
|
long timezone = 0;
|
||||||
int daylight = 0;
|
int daylight = 0;
|
||||||
|
|
||||||
|
|
||||||
namespace BPrivate {
|
|
||||||
|
|
||||||
|
|
||||||
static time_zone_info tzInfo;
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
tzset(void)
|
tzset(void)
|
||||||
{
|
{
|
||||||
char path[B_PATH_NAME_LENGTH];
|
if (gLocaleBackend == NULL && LocaleBackend::LoadBackend() != B_OK)
|
||||||
if (find_directory(B_COMMON_SETTINGS_DIRECTORY, -1, false, path,
|
|
||||||
sizeof(path)) < 0)
|
|
||||||
return;
|
|
||||||
strlcat(path, "/", sizeof(path));
|
|
||||||
strlcat(path, skPosixTimeZoneInfoFile, sizeof(path));
|
|
||||||
|
|
||||||
FILE* tzInfoFile = fopen(path, "r");
|
|
||||||
if (tzInfoFile == NULL)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
size_t numRead = fread(&tzInfo, sizeof(tzInfo), 1, tzInfoFile);
|
char timeZoneID[64] = { "GMT" };
|
||||||
fclose(tzInfoFile);
|
|
||||||
|
|
||||||
if (numRead != 1)
|
const char* tz = getenv("TZ");
|
||||||
return;
|
if (tz != NULL)
|
||||||
|
strlcpy(timeZoneID, tz, sizeof(timeZoneID));
|
||||||
|
else {
|
||||||
|
do {
|
||||||
|
char path[B_PATH_NAME_LENGTH];
|
||||||
|
if (find_directory(B_COMMON_SETTINGS_DIRECTORY, -1, false, path,
|
||||||
|
sizeof(path)) < 0)
|
||||||
|
break;
|
||||||
|
strlcat(path, "/libroot_timezone_info", sizeof(path));
|
||||||
|
|
||||||
tzname[0] = tzInfo.short_std_name;
|
FILE* tzInfoFile = fopen(path, "r");
|
||||||
tzname[1] = tzInfo.short_dst_name;
|
if (tzInfoFile == NULL)
|
||||||
timezone = tzInfo.offset_from_gmt;
|
break;
|
||||||
daylight = tzInfo.uses_daylight_saving;
|
|
||||||
|
fgets(timeZoneID, sizeof(timeZoneID), tzInfoFile);
|
||||||
|
fclose(tzInfoFile);
|
||||||
|
} while(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gLocaleBackend != NULL) {
|
||||||
|
gLocaleBackend->TZSet(timeZoneID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace BPrivate
|
extern "C" struct tm*
|
||||||
|
localtime(const time_t* inTime)
|
||||||
|
{
|
||||||
|
static tm tm;
|
||||||
|
|
||||||
|
return localtime_r(inTime, &tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" struct tm*
|
||||||
|
localtime_r(const time_t* inTime, struct tm* tmOut)
|
||||||
|
{
|
||||||
|
if (inTime == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tzset();
|
||||||
|
if (gLocaleBackend != NULL) {
|
||||||
|
status_t status = gLocaleBackend->Localtime(inTime, tmOut);
|
||||||
|
|
||||||
|
if (status != B_OK)
|
||||||
|
errno = EOVERFLOW;
|
||||||
|
|
||||||
|
return tmOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = ENOSYS;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" struct tm*
|
||||||
|
gmtime(const time_t* inTime)
|
||||||
|
{
|
||||||
|
static tm tm;
|
||||||
|
|
||||||
|
return gmtime_r(inTime, &tm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" struct tm*
|
||||||
|
gmtime_r(const time_t* inTime, struct tm* tmOut)
|
||||||
|
{
|
||||||
|
if (inTime == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
tzset();
|
||||||
|
if (gLocaleBackend != NULL) {
|
||||||
|
status_t status = gLocaleBackend->Gmtime(inTime, tmOut);
|
||||||
|
|
||||||
|
if (status != B_OK)
|
||||||
|
errno = EOVERFLOW;
|
||||||
|
|
||||||
|
return tmOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = ENOSYS;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" time_t
|
||||||
|
mktime(struct tm* inTm)
|
||||||
|
{
|
||||||
|
if (inTm == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tzset();
|
||||||
|
if (gLocaleBackend != NULL) {
|
||||||
|
time_t timeOut;
|
||||||
|
status_t status = gLocaleBackend->Mktime(inTm, timeOut);
|
||||||
|
|
||||||
|
if (status != B_OK) {
|
||||||
|
errno = EOVERFLOW;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1321,6 +1321,7 @@ struct tm * const tmp;
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
struct tm *
|
struct tm *
|
||||||
localtime(timep)
|
localtime(timep)
|
||||||
const time_t * const timep;
|
const time_t * const timep;
|
||||||
@@ -1340,6 +1341,7 @@ struct tm * tmp;
|
|||||||
{
|
{
|
||||||
return localsub(timep, 0L, tmp);
|
return localsub(timep, 0L, tmp);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** gmtsub is to gmtime as localsub is to localtime.
|
** gmtsub is to gmtime as localsub is to localtime.
|
||||||
@@ -1384,6 +1386,7 @@ struct tm * const tmp;
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
struct tm *
|
struct tm *
|
||||||
gmtime(timep)
|
gmtime(timep)
|
||||||
const time_t * const timep;
|
const time_t * const timep;
|
||||||
@@ -1403,6 +1406,8 @@ struct tm * tmp;
|
|||||||
return gmtsub(timep, 0L, tmp);
|
return gmtsub(timep, 0L, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef STD_INSPIRED
|
#ifdef STD_INSPIRED
|
||||||
|
|
||||||
struct tm *
|
struct tm *
|
||||||
@@ -1932,6 +1937,7 @@ const long offset;
|
|||||||
return WRONG;
|
return WRONG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
time_t
|
time_t
|
||||||
mktime(tmp)
|
mktime(tmp)
|
||||||
struct tm * const tmp;
|
struct tm * const tmp;
|
||||||
@@ -1939,6 +1945,7 @@ struct tm * const tmp;
|
|||||||
tzset();
|
tzset();
|
||||||
return time1(tmp, localsub, 0L);
|
return time1(tmp, localsub, 0L);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef STD_INSPIRED
|
#ifndef STD_INSPIRED
|
||||||
#pragma weak timelocal=mktime
|
#pragma weak timelocal=mktime
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ SimpleTest signal_in_allocator_test : signal_in_allocator_test.cpp ;
|
|||||||
SimpleTest signal_in_allocator_test2 : signal_in_allocator_test2.cpp ;
|
SimpleTest signal_in_allocator_test2 : signal_in_allocator_test2.cpp ;
|
||||||
SimpleTest signal_test : signal_test.cpp ;
|
SimpleTest signal_test : signal_test.cpp ;
|
||||||
SimpleTest sigsetjmp_test : sigsetjmp_test.c ;
|
SimpleTest sigsetjmp_test : sigsetjmp_test.c ;
|
||||||
|
SimpleTest test_time : test_time.c ;
|
||||||
|
SimpleTest tst-mktime : tst-mktime.c ;
|
||||||
SimpleTest <test>truncate : truncate.cpp ;
|
SimpleTest <test>truncate : truncate.cpp ;
|
||||||
SimpleTest init_rld_after_fork_test : init_rld_after_fork_test.cpp ;
|
SimpleTest init_rld_after_fork_test : init_rld_after_fork_test.cpp ;
|
||||||
|
|
||||||
|
|||||||
@@ -1545,6 +1545,303 @@ test_collation()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - time conversion ----------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
test_localtime(const char* tz, time_t nowSecs, const tm& expected)
|
||||||
|
{
|
||||||
|
setenv("TZ", tz, 1);
|
||||||
|
printf("localtime for '%s'\n", tz);
|
||||||
|
|
||||||
|
tm now;
|
||||||
|
tm* result = localtime_r(&nowSecs, &now);
|
||||||
|
int problemCount = 0;
|
||||||
|
if (result == NULL) {
|
||||||
|
printf("\tPROBLEM: localtime(\"%ld\") = NULL\n", nowSecs);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_year != expected.tm_year) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_year = %d (expected %d)\n",
|
||||||
|
now.tm_year, expected.tm_year);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_mon != expected.tm_mon) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_mon = %d (expected %d)\n",
|
||||||
|
now.tm_mon, expected.tm_mon);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_mday != expected.tm_mday) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_mday = %d (expected %d)\n",
|
||||||
|
now.tm_mday, expected.tm_mday);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_hour != expected.tm_hour) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_hour = %d (expected %d)\n",
|
||||||
|
now.tm_hour, expected.tm_hour);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_min != expected.tm_min) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_min = %d (expected %d)\n",
|
||||||
|
now.tm_min, expected.tm_min);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_sec != expected.tm_sec) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_sec = %d (expected %d)\n",
|
||||||
|
now.tm_sec, expected.tm_sec);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_wday != expected.tm_wday) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_wday = %d (expected %d)\n",
|
||||||
|
now.tm_wday, expected.tm_wday);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_yday != expected.tm_yday) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_yday = %d (expected %d)\n",
|
||||||
|
now.tm_yday, expected.tm_yday);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_isdst != expected.tm_isdst) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_isdst = %d (expected %d)\n",
|
||||||
|
now.tm_isdst, expected.tm_isdst);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_gmtoff != expected.tm_gmtoff) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_gmtoff = %d (expected %d)\n",
|
||||||
|
now.tm_gmtoff, expected.tm_gmtoff);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (strcasecmp(now.tm_zone, expected.tm_zone) != 0) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_zone = '%s' (expected '%s')\n",
|
||||||
|
now.tm_zone, expected.tm_zone);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (problemCount)
|
||||||
|
printf("\t%d problem(s) found!\n", problemCount);
|
||||||
|
else
|
||||||
|
printf("\tall fine\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
test_gmtime(const char* tz, time_t nowSecs, const tm& expected)
|
||||||
|
{
|
||||||
|
setenv("TZ", tz, 1);
|
||||||
|
printf("gmtime for '%s'\n", tz);
|
||||||
|
|
||||||
|
tm now;
|
||||||
|
tm* result = gmtime_r(&nowSecs, &now);
|
||||||
|
int problemCount = 0;
|
||||||
|
if (result == NULL) {
|
||||||
|
printf("\tPROBLEM: localtime(\"%ld\") = NULL\n", nowSecs);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_year != expected.tm_year) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_year = %d (expected %d)\n",
|
||||||
|
now.tm_year, expected.tm_year);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_mon != expected.tm_mon) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_mon = %d (expected %d)\n",
|
||||||
|
now.tm_mon, expected.tm_mon);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_mday != expected.tm_mday) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_mday = %d (expected %d)\n",
|
||||||
|
now.tm_mday, expected.tm_mday);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_hour != expected.tm_hour) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_hour = %d (expected %d)\n",
|
||||||
|
now.tm_hour, expected.tm_hour);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_min != expected.tm_min) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_min = %d (expected %d)\n",
|
||||||
|
now.tm_min, expected.tm_min);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_sec != expected.tm_sec) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_sec = %d (expected %d)\n",
|
||||||
|
now.tm_sec, expected.tm_sec);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_wday != expected.tm_wday) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_wday = %d (expected %d)\n",
|
||||||
|
now.tm_wday, expected.tm_wday);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_yday != expected.tm_yday) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_yday = %d (expected %d)\n",
|
||||||
|
now.tm_yday, expected.tm_yday);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_isdst != expected.tm_isdst) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_isdst = %d (expected %d)\n",
|
||||||
|
now.tm_isdst, expected.tm_isdst);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (now.tm_gmtoff != expected.tm_gmtoff) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_gmtoff = %d (expected %d)\n",
|
||||||
|
now.tm_gmtoff, expected.tm_gmtoff);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (strcasecmp(now.tm_zone, expected.tm_zone) != 0) {
|
||||||
|
printf("\tPROBLEM: localtime().tm_zone = '%s' (expected '%s')\n",
|
||||||
|
now.tm_zone, expected.tm_zone);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (problemCount)
|
||||||
|
printf("\t%d problem(s) found!\n", problemCount);
|
||||||
|
else
|
||||||
|
printf("\tall fine\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
test_mktime(const char* tz, tm& tm, time_t expected, int expectedWeekDay,
|
||||||
|
int expectedYearDay)
|
||||||
|
{
|
||||||
|
setenv("TZ", tz, 1);
|
||||||
|
printf("mktime for '%s'\n", tz);
|
||||||
|
|
||||||
|
time_t result = mktime(&tm);
|
||||||
|
int problemCount = 0;
|
||||||
|
if (result != expected) {
|
||||||
|
printf("\tPROBLEM: mktime() = %ld (expected %ld)\n", result, expected);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (tm.tm_wday != expectedWeekDay) {
|
||||||
|
printf("\tPROBLEM: mktime().tm_wday = %d (expected %d)\n",
|
||||||
|
tm.tm_wday, expectedWeekDay);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (tm.tm_yday != expectedYearDay) {
|
||||||
|
printf("\tPROBLEM: mktime().tm_yday = %d (expected %d)\n",
|
||||||
|
tm.tm_yday, expectedYearDay);
|
||||||
|
problemCount++;
|
||||||
|
}
|
||||||
|
if (problemCount)
|
||||||
|
printf("\t%d problem(s) found!\n", problemCount);
|
||||||
|
else
|
||||||
|
printf("\tall fine\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
test_timeconversions()
|
||||||
|
{
|
||||||
|
setlocale(LC_ALL, "");
|
||||||
|
{
|
||||||
|
time_t testTime = 1279391169; // Sat Jul 17 18:26:09 GMT 2010
|
||||||
|
tm gtm = {
|
||||||
|
9, 26, 18, 17, 6, 110, 6, 197, 0, 0, (char*)"GMT"
|
||||||
|
};
|
||||||
|
test_localtime("GMT", testTime, gtm);
|
||||||
|
test_gmtime("GMT", testTime, gtm);
|
||||||
|
gtm.tm_wday = -1;
|
||||||
|
gtm.tm_yday = -1;
|
||||||
|
test_mktime("GMT", gtm, testTime, 6, 197);
|
||||||
|
tm btm = {
|
||||||
|
9, 26, 20, 17, 6, 110, 6, 197, 1, 2 * 3600, (char*)"CEST"
|
||||||
|
};
|
||||||
|
test_localtime("Europe/Berlin", testTime, btm);
|
||||||
|
test_gmtime("Europe/Berlin", testTime, gtm);
|
||||||
|
btm.tm_wday = -1;
|
||||||
|
btm.tm_yday = -1;
|
||||||
|
test_mktime("Europe/Berlin", btm, testTime, 6, 197);
|
||||||
|
tm latm = {
|
||||||
|
9, 26, 11, 17, 6, 110, 6, 197, 1, -7 * 3600, (char*)"PDT"
|
||||||
|
};
|
||||||
|
test_localtime("America/Los_Angeles", testTime, latm);
|
||||||
|
test_gmtime("America/Los_Angeles", testTime, gtm);
|
||||||
|
latm.tm_wday = -1;
|
||||||
|
latm.tm_yday = -1;
|
||||||
|
test_mktime("America/Los_Angeles", latm, testTime, 6, 197);
|
||||||
|
tm ttm = {
|
||||||
|
9, 26, 3, 18, 6, 110, 0, 198, 0, 9 * 3600, (char*)"JST"
|
||||||
|
};
|
||||||
|
test_localtime("Asia/Tokyo", testTime, ttm);
|
||||||
|
test_gmtime("Asia/Tokyo", testTime, gtm);
|
||||||
|
ttm.tm_wday = -1;
|
||||||
|
ttm.tm_yday = -1;
|
||||||
|
test_mktime("Asia/Tokyo", ttm, testTime, 0, 198);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
time_t testTime = 1268159169; // Tue Mar 9 18:26:09 GMT 2010
|
||||||
|
tm gtm = {
|
||||||
|
9, 26, 18, 9, 2, 110, 2, 67, 0, 0, (char*)"GMT"
|
||||||
|
};
|
||||||
|
test_localtime("GMT", testTime, gtm);
|
||||||
|
test_gmtime("GMT", testTime, gtm);
|
||||||
|
gtm.tm_wday = -1;
|
||||||
|
gtm.tm_yday = -1;
|
||||||
|
test_mktime("GMT", gtm, testTime, 2, 67);
|
||||||
|
tm btm = {
|
||||||
|
9, 26, 19, 9, 2, 110, 2, 67, 0, 3600, (char*)"CET"
|
||||||
|
};
|
||||||
|
test_localtime("Europe/Berlin", testTime, btm);
|
||||||
|
test_gmtime("Europe/Berlin", testTime, gtm);
|
||||||
|
btm.tm_wday = -1;
|
||||||
|
btm.tm_yday = -1;
|
||||||
|
test_mktime("Europe/Berlin", btm, testTime, 2, 67);
|
||||||
|
tm latm = {
|
||||||
|
9, 26, 10, 9, 2, 110, 2, 67, 0, -8 * 3600, (char*)"PST"
|
||||||
|
};
|
||||||
|
test_localtime("America/Los_Angeles", testTime, latm);
|
||||||
|
test_gmtime("America/Los_Angeles", testTime, gtm);
|
||||||
|
latm.tm_wday = -1;
|
||||||
|
latm.tm_yday = -1;
|
||||||
|
test_mktime("America/Los_Angeles", latm, testTime, 2, 67);
|
||||||
|
tm ttm = {
|
||||||
|
9, 26, 3, 10, 2, 110, 3, 68, 0, 9 * 3600, (char*)"JST"
|
||||||
|
};
|
||||||
|
test_localtime("Asia/Tokyo", testTime, ttm);
|
||||||
|
test_gmtime("Asia/Tokyo", testTime, gtm);
|
||||||
|
ttm.tm_wday = -1;
|
||||||
|
ttm.tm_yday = -1;
|
||||||
|
test_mktime("Asia/Tokyo", ttm, testTime, 3, 68);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
time_t testTime = 0; // Thu Jan 1 00:00:00 GMT 1970
|
||||||
|
tm gtm = {
|
||||||
|
0, 0, 0, 1, 0, 70, 4, 0, 0, 0, (char*)"GMT"
|
||||||
|
};
|
||||||
|
test_localtime("GMT", testTime, gtm);
|
||||||
|
test_gmtime("GMT", testTime, gtm);
|
||||||
|
gtm.tm_wday = -1;
|
||||||
|
gtm.tm_yday = -1;
|
||||||
|
test_mktime("GMT", gtm, testTime, 4, 0);
|
||||||
|
tm btm = {
|
||||||
|
0, 0, 1, 1, 0, 70, 4, 0, 0, 1 * 3600, (char*)"CET"
|
||||||
|
};
|
||||||
|
test_localtime("Europe/Berlin", testTime, btm);
|
||||||
|
test_gmtime("Europe/Berlin", testTime, gtm);
|
||||||
|
btm.tm_wday = -1;
|
||||||
|
btm.tm_yday = -1;
|
||||||
|
test_mktime("Europe/Berlin", btm, testTime, 4, 0);
|
||||||
|
tm latm = {
|
||||||
|
0, 0, 16, 31, 11, 69, 3, 364, 0, -8 * 3600, (char*)"PST"
|
||||||
|
};
|
||||||
|
test_localtime("America/Los_Angeles", testTime, latm);
|
||||||
|
test_gmtime("America/Los_Angeles", testTime, gtm);
|
||||||
|
latm.tm_wday = -1;
|
||||||
|
latm.tm_yday = -1;
|
||||||
|
test_mktime("America/Los_Angeles", latm, testTime, 3, 364);
|
||||||
|
tm ttm = {
|
||||||
|
0, 0, 9, 1, 0, 70, 4, 0, 0, 9 * 3600, (char*)"JST"
|
||||||
|
};
|
||||||
|
test_localtime("Asia/Tokyo", testTime, ttm);
|
||||||
|
test_gmtime("Asia/Tokyo", testTime, gtm);
|
||||||
|
ttm.tm_wday = -1;
|
||||||
|
ttm.tm_yday = -1;
|
||||||
|
test_mktime("Asia/Tokyo", ttm, testTime, 4, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - main ---------------------------------------------------------
|
// #pragma mark - main ---------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
@@ -1563,6 +1860,7 @@ main(void)
|
|||||||
test_wctrans();
|
test_wctrans();
|
||||||
test_langinfo();
|
test_langinfo();
|
||||||
test_collation();
|
test_collation();
|
||||||
|
test_timeconversions();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/* Copyright (C) 1991, 1992, 1994, 1997 Free Software Foundation, Inc.
|
||||||
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the GNU C Library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
time_t t;
|
||||||
|
register struct tm *tp;
|
||||||
|
struct tm tbuf;
|
||||||
|
int lose = 0;
|
||||||
|
|
||||||
|
--argc;
|
||||||
|
++argv;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
if (argc > 0)
|
||||||
|
{
|
||||||
|
static char buf[BUFSIZ];
|
||||||
|
sprintf(buf, "TZ=%s", *argv);
|
||||||
|
if (putenv(buf))
|
||||||
|
{
|
||||||
|
puts("putenv failed.");
|
||||||
|
lose = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
puts (buf);
|
||||||
|
}
|
||||||
|
tzset();
|
||||||
|
tbuf.tm_year = 72;
|
||||||
|
tbuf.tm_mon = 0;
|
||||||
|
tbuf.tm_mday = 31;
|
||||||
|
tbuf.tm_hour = 6;
|
||||||
|
tbuf.tm_min = 14;
|
||||||
|
tbuf.tm_sec = 50;
|
||||||
|
tbuf.tm_isdst = -1;
|
||||||
|
doit:;
|
||||||
|
t = mktime(&tbuf);
|
||||||
|
if (t == (time_t) -1)
|
||||||
|
{
|
||||||
|
puts("mktime() failed?");
|
||||||
|
lose = 1;
|
||||||
|
}
|
||||||
|
tp = localtime(&t);
|
||||||
|
if (tp == NULL)
|
||||||
|
{
|
||||||
|
puts("localtime() failed.");
|
||||||
|
lose = 1;
|
||||||
|
}
|
||||||
|
else if (strftime(buf, sizeof(buf), "%a %b %d %X %Z %Y", tp) == 0)
|
||||||
|
{
|
||||||
|
puts("strftime() failed.");
|
||||||
|
lose = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
puts(buf);
|
||||||
|
if (tbuf.tm_year == 101)
|
||||||
|
{
|
||||||
|
tbuf.tm_year = 97;
|
||||||
|
tbuf.tm_mon = 0;
|
||||||
|
goto doit;
|
||||||
|
}
|
||||||
|
++argv;
|
||||||
|
} while (--argc > 0);
|
||||||
|
|
||||||
|
{
|
||||||
|
#define SIZE 256
|
||||||
|
char buffer[SIZE];
|
||||||
|
time_t curtime;
|
||||||
|
struct tm *loctime;
|
||||||
|
|
||||||
|
curtime = time (NULL);
|
||||||
|
|
||||||
|
loctime = localtime (&curtime);
|
||||||
|
|
||||||
|
fputs (asctime (loctime), stdout);
|
||||||
|
|
||||||
|
strftime (buffer, SIZE, "Today is %A, %B %d.\n", loctime);
|
||||||
|
fputs (buffer, stdout);
|
||||||
|
strftime (buffer, SIZE, "The time is %I:%M %p.\n", loctime);
|
||||||
|
fputs (buffer, stdout);
|
||||||
|
|
||||||
|
loctime->tm_year = 72;
|
||||||
|
loctime->tm_mon = 8;
|
||||||
|
loctime->tm_mday = 12;
|
||||||
|
loctime->tm_hour = 20;
|
||||||
|
loctime->tm_min = 49;
|
||||||
|
loctime->tm_sec = 05;
|
||||||
|
curtime = mktime (loctime);
|
||||||
|
strftime (buffer, SIZE, "%D %T was %w the %jth.\n", loctime);
|
||||||
|
fputs (buffer, stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (lose ? EXIT_FAILURE : EXIT_SUCCESS);
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
struct tm time_str, *tm;
|
||||||
|
time_t t;
|
||||||
|
char daybuf[20];
|
||||||
|
int result;
|
||||||
|
|
||||||
|
time_str.tm_year = 2001 - 1900;
|
||||||
|
time_str.tm_mon = 7 - 1;
|
||||||
|
time_str.tm_mday = 4;
|
||||||
|
time_str.tm_hour = 0;
|
||||||
|
time_str.tm_min = 0;
|
||||||
|
time_str.tm_sec = 1;
|
||||||
|
time_str.tm_isdst = -1;
|
||||||
|
|
||||||
|
if (mktime (&time_str) == -1)
|
||||||
|
{
|
||||||
|
(void) puts ("-unknown-");
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(void) strftime (daybuf, sizeof (daybuf), "%A", &time_str);
|
||||||
|
(void) puts (daybuf);
|
||||||
|
result = strcmp (daybuf, "Wednesday") != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setenv ("TZ", "EST+5", 1);
|
||||||
|
#define EVENING69 1 * 60 * 60 + 2 * 60 + 29
|
||||||
|
t = EVENING69;
|
||||||
|
tm = localtime (&t);
|
||||||
|
if (tm == NULL)
|
||||||
|
{
|
||||||
|
(void) puts ("localtime returned NULL");
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
time_str = *tm;
|
||||||
|
t = mktime (&time_str);
|
||||||
|
if (t != EVENING69)
|
||||||
|
{
|
||||||
|
printf ("mktime returned %ld, expected %d\n",
|
||||||
|
(long) t, EVENING69);
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
(void) puts ("Dec 31 1969 EST test passed");
|
||||||
|
|
||||||
|
setenv ("TZ", "CET-1", 1);
|
||||||
|
t = mktime (&time_str);
|
||||||
|
if (t != (time_t) -1)
|
||||||
|
{
|
||||||
|
printf ("mktime returned %ld, expected -1\n", (long) t);
|
||||||
|
result = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
(void) puts ("Dec 31 1969 CET test passed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user