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

source code of qtbase/src/corelib/time/qtimezonelocale.cpp