1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include <private/qtimezonelocale_p.h>
#include <private/qtimezoneprivate_p.h>
#if !QT_CONFIG(icu)
# include <private/qdatetime_p.h>
// Use data generated from CLDR:
# include <private/qtimezonelocale_data_p.h>
# include <private/qtimezoneprivate_data_p.h>
#endif
QT_BEGIN_NAMESPACE
#if QT_CONFIG(icu) // Get data from ICU:
namespace {
// Convert TimeType and NameType into ICU UCalendarDisplayNameType
constexpr UCalendarDisplayNameType ucalDisplayNameType(QTimeZone::TimeType timeType,
QTimeZone::NameType nameType)
{
// TODO ICU C UCalendarDisplayNameType does not support full set of C++ TimeZone::EDisplayType
// For now, treat Generic as Standard
switch (nameType) {
case QTimeZone::OffsetName:
Q_UNREACHABLE(); // Callers of ucalTimeZoneDisplayName() should take care of OffsetName.
case QTimeZone::ShortName:
return timeType == QTimeZone::DaylightTime ? UCAL_SHORT_DST : UCAL_SHORT_STANDARD;
case QTimeZone::DefaultName:
case QTimeZone::LongName:
return timeType == QTimeZone::DaylightTime ? UCAL_DST : UCAL_STANDARD;
}
Q_UNREACHABLE_RETURN(UCAL_STANDARD);
}
} // nameless namespace
namespace QtTimeZoneLocale {
// Qt wrapper around ucal_getTimeZoneDisplayName()
// Used directly by ICU backend; indirectly by TZ (see below).
QString ucalTimeZoneDisplayName(UCalendar *ucal,
QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QByteArray &localeCode)
{
constexpr int32_t BigNameLength = 50;
int32_t size = BigNameLength;
QString result(size, Qt::Uninitialized);
auto dst = [&result]() { return reinterpret_cast<UChar *>(result.data()); };
UErrorCode status = U_ZERO_ERROR;
const UCalendarDisplayNameType utype = ucalDisplayNameType(timeType, nameType);
// size = ucal_getTimeZoneDisplayName(cal, type, locale, result, resultLength, status)
size = ucal_getTimeZoneDisplayName(ucal, utype, localeCode.constData(),
dst(), size, &status);
// If overflow, then resize and retry
if (size > BigNameLength || status == U_BUFFER_OVERFLOW_ERROR) {
result.resize(size);
status = U_ZERO_ERROR;
size = ucal_getTimeZoneDisplayName(ucal, utype, localeCode.constData(),
dst(), size, &status);
}
if (!U_SUCCESS(status))
return QString();
// Resize and return:
result.resize(size);
return result;
}
} // QtTimeZoneLocale
// Used by TZ backends when ICU is available:
QString QTimeZonePrivate::localeName(qint64 atMSecsSinceEpoch, int offsetFromUtc,
QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const
{
Q_UNUSED(atMSecsSinceEpoch);
// TODO: use CLDR data for the offset name.
// No ICU API for offset formats, so fall back to our ISO one, even if
// locale isn't C:
if (nameType == QTimeZone::OffsetName)
return isoOffsetFormat(offsetFromUtc);
const QString id = QString::fromUtf8(m_id);
const QByteArray loc = locale.name().toUtf8();
UErrorCode status = U_ZERO_ERROR;
UCalendar *ucal = ucal_open(reinterpret_cast<const UChar *>(id.data()), id.size(),
loc.constData(), UCAL_DEFAULT, &status);
if (ucal && U_SUCCESS(status)) {
auto tidier = qScopeGuard([ucal]() { ucal_close(ucal); });
return QtTimeZoneLocale::ucalTimeZoneDisplayName(ucal, timeType, nameType, loc);
}
return QString();
}
#else // No ICU, use QTZ[LP}_data_p.h data for feature timezone_locale.
namespace {
using namespace QtTimeZoneLocale; // QTZL_data_p.h
using namespace QtTimeZoneCldr; // QTZP_data_p.h
// Accessors for the QTZL_data_p.h
// Accessors for the QTZP_data_p.h
} // nameless namespace
QString QTimeZonePrivate::localeName(qint64 atMSecsSinceEpoch, int offsetFromUtc,
QTimeZone::TimeType timeType,
QTimeZone::NameType nameType,
const QLocale &locale) const
{
Q_ASSERT(nameType != QTimeZone::OffsetName || locale.language() != QLocale::C);
// Get data from QTZ[LP]_data_p.h
Q_UNUSED(atMSecsSinceEpoch);
Q_UNUSED(offsetFromUtc);
Q_UNUSED(timeType);
return QString();
}
#endif // ICU
QT_END_NAMESPACE
|