QTzTimeZonePrivate: introduce PosixZone class
... as a replacement for QPair<QString, int>, and move some repsonsibilities into it. This avoids the repeated use of the magic number INT_MIN to indicate absence of an offset and does away with the confusing .first and .second, replacing them instead with proper names, .name and .offset. Change-Id: I0f6906467b8efa16bed2bf5677f2bbbd534da1ae Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
c585802e94
commit
adca47cbc1
@ -452,13 +452,31 @@ static inline bool asciiIsLetter(char ch)
|
||||
return ch >= 'a' && ch <= 'z';
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct PosixZone
|
||||
{
|
||||
enum {
|
||||
InvalidOffset = INT_MIN,
|
||||
};
|
||||
|
||||
QString name;
|
||||
int offset;
|
||||
|
||||
static PosixZone invalid() { return {QString(), InvalidOffset}; }
|
||||
static PosixZone parse(const char *&pos, const char *end);
|
||||
|
||||
bool hasValidOffset() const Q_DECL_NOTHROW { return offset != InvalidOffset; }
|
||||
};
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
// Returns the zone name, the offset (in seconds) and advances \a begin to
|
||||
// where the parsing ended. Returns a zone of INT_MIN in case an offset
|
||||
// couldn't be read.
|
||||
static QPair<QString, int> parsePosixZoneNameAndOffset(const char *&pos, const char *end)
|
||||
PosixZone PosixZone::parse(const char *&pos, const char *end)
|
||||
{
|
||||
static const char offsetChars[] = "0123456789:";
|
||||
QPair<QString, int> result = qMakePair(QString(), INT_MIN);
|
||||
|
||||
const char *nameBegin = pos;
|
||||
const char *nameEnd;
|
||||
@ -480,7 +498,7 @@ static QPair<QString, int> parsePosixZoneNameAndOffset(const char *&pos, const c
|
||||
pos = nameEnd;
|
||||
}
|
||||
if (nameEnd - nameBegin < 3)
|
||||
return result; // name must be at least 3 characters long
|
||||
return invalid(); // name must be at least 3 characters long
|
||||
|
||||
// zone offset, form [+-]hh:mm:ss
|
||||
const char *zoneBegin = pos;
|
||||
@ -493,11 +511,10 @@ static QPair<QString, int> parsePosixZoneNameAndOffset(const char *&pos, const c
|
||||
++zoneEnd;
|
||||
}
|
||||
|
||||
result.first = QString::fromUtf8(nameBegin, nameEnd - nameBegin);
|
||||
if (zoneEnd > zoneBegin)
|
||||
result.second = parsePosixOffset(zoneBegin, zoneEnd);
|
||||
QString name = QString::fromUtf8(nameBegin, nameEnd - nameBegin);
|
||||
const int offset = zoneEnd > zoneBegin ? parsePosixOffset(zoneBegin, zoneEnd) : InvalidOffset;
|
||||
pos = zoneEnd;
|
||||
return result;
|
||||
return {std::move(name), offset};
|
||||
}
|
||||
|
||||
static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule,
|
||||
@ -517,19 +534,19 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
|
||||
// See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
|
||||
QList<QByteArray> parts = posixRule.split(',');
|
||||
|
||||
QPair<QString, int> stdZone, dstZone;
|
||||
PosixZone stdZone, dstZone;
|
||||
{
|
||||
const QByteArray &zoneinfo = parts.at(0);
|
||||
const char *begin = zoneinfo.constBegin();
|
||||
|
||||
stdZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd());
|
||||
if (stdZone.second == INT_MIN) {
|
||||
stdZone.second = 0; // reset to UTC if we failed to parse
|
||||
stdZone = PosixZone::parse(begin, zoneinfo.constEnd());
|
||||
if (!stdZone.hasValidOffset()) {
|
||||
stdZone.offset = 0; // reset to UTC if we failed to parse
|
||||
} else if (begin < zoneinfo.constEnd()) {
|
||||
dstZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd());
|
||||
if (dstZone.second == INT_MIN) {
|
||||
dstZone = PosixZone::parse(begin, zoneinfo.constEnd());
|
||||
if (!dstZone.hasValidOffset()) {
|
||||
// if the dst offset isn't provided, it is 1 hour ahead of the standard offset
|
||||
dstZone.second = stdZone.second + (60 * 60);
|
||||
dstZone.offset = stdZone.offset + (60 * 60);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -538,10 +555,10 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
|
||||
if (parts.count() == 1) {
|
||||
QTimeZonePrivate::Data data;
|
||||
data.atMSecsSinceEpoch = lastTranMSecs;
|
||||
data.offsetFromUtc = stdZone.second;
|
||||
data.standardTimeOffset = stdZone.second;
|
||||
data.offsetFromUtc = stdZone.offset;
|
||||
data.standardTimeOffset = stdZone.offset;
|
||||
data.daylightTimeOffset = 0;
|
||||
data.abbreviation = stdZone.first;
|
||||
data.abbreviation = stdZone.name;
|
||||
result << data;
|
||||
return result;
|
||||
}
|
||||
@ -568,18 +585,18 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
|
||||
for (int year = startYear; year <= endYear; ++year) {
|
||||
QTimeZonePrivate::Data dstData;
|
||||
QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC);
|
||||
dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.second * 1000);
|
||||
dstData.offsetFromUtc = dstZone.second;
|
||||
dstData.standardTimeOffset = stdZone.second;
|
||||
dstData.daylightTimeOffset = dstZone.second - stdZone.second;
|
||||
dstData.abbreviation = dstZone.first;
|
||||
dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.offset * 1000);
|
||||
dstData.offsetFromUtc = dstZone.offset;
|
||||
dstData.standardTimeOffset = stdZone.offset;
|
||||
dstData.daylightTimeOffset = dstZone.offset - stdZone.offset;
|
||||
dstData.abbreviation = dstZone.name;
|
||||
QTimeZonePrivate::Data stdData;
|
||||
QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC);
|
||||
stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.second * 1000);
|
||||
stdData.offsetFromUtc = stdZone.second;
|
||||
stdData.standardTimeOffset = stdZone.second;
|
||||
stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.offset * 1000);
|
||||
stdData.offsetFromUtc = stdZone.offset;
|
||||
stdData.standardTimeOffset = stdZone.offset;
|
||||
stdData.daylightTimeOffset = 0;
|
||||
stdData.abbreviation = stdZone.first;
|
||||
stdData.abbreviation = stdZone.name;
|
||||
// Part of the high year will overflow
|
||||
if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
|
||||
if (dstData.atMSecsSinceEpoch > 0) {
|
||||
|
Loading…
Reference in New Issue
Block a user