11using namespace std::chrono;
12using namespace std::chrono_literals;
14#define EXCEPTION_CHECKED(expression, fallback)
17 } QT_CATCH (const std::runtime_error &) {
24 return sys_time<milliseconds>(milliseconds(millis));
30 EXCEPTION_CHECKED(
return zone->get_info(chronoForEpochMillis(millis)),
return std::nullopt);
40 const tzdb &db = get_tzdb();
41 std::vector<std::string_view> raw, links, all;
42 auto now = system_clock::now();
43 for (
const time_zone &zone : db.zones) {
45 const sys_info info = zone.get_info(now);
46 if (info.offset.count() != *offset)
49 raw.push_back(zone.name());
51 for (
const time_zone_link &link : db.links) {
53 const std::string_view target = link.target();
54 const time_zone *zone = db.locate_zone(target);
55 const sys_info info = zone->get_info(now);
56 if (info.offset.count() != *offset)
59 links.push_back(link.name());
62 all.reserve(raw.size() + links.size());
63 std::set_union(raw.begin(), raw.end(), links.begin(), links.end(), std::back_inserter(all));
77fromSysInfo(std::chrono::sys_info info, qint64 atMSecsSinceEpoch)
79 QString abbreviation = QString::fromLatin1(info.abbrev);
80 int offsetFromUtc = info.offset.count();
82 int standardTimeOffset = offsetFromUtc - seconds(info.save).count();
83 return QChronoTimeZonePrivate::Data(abbreviation, atMSecsSinceEpoch,
84 offsetFromUtc, standardTimeOffset);
87QChronoTimeZonePrivate::QChronoTimeZonePrivate()
88 : m_timeZone(std::chrono::current_zone())
91 m_id.assign(m_timeZone->name());
94QChronoTimeZonePrivate::QChronoTimeZonePrivate(QByteArrayView id)
95 : m_timeZone(idToZone(std::string_view(id.data(), id.size())))
98 m_id.assign(m_timeZone->name());
101QChronoTimeZonePrivate *QChronoTimeZonePrivate::clone()
const
103 return new QChronoTimeZonePrivate(*
this);
106QChronoTimeZonePrivate::~QChronoTimeZonePrivate()
109QByteArray QChronoTimeZonePrivate::systemTimeZoneId()
const
111 if (
const time_zone *zone = std::chrono::current_zone()) {
112 std::string_view name = zone->name();
113 return {name.data(), qsizetype(name.size())};
118bool QChronoTimeZonePrivate::isTimeZoneIdAvailable(
const QByteArray &ianaId)
const
120 return idToZone(std::string_view(ianaId.data(), ianaId.size())) !=
nullptr;
123QList<QByteArray> QChronoTimeZonePrivate::availableTimeZoneIds()
const
125 QList<QByteArray> result;
126 if (
auto ids = allZoneIds()) {
127 result.reserve(ids->size());
128 for (std::string_view id : *ids)
129 result << QByteArray{id.data(), qsizetype(id.size())};
135QList<QByteArray> QChronoTimeZonePrivate::availableTimeZoneIds(
int utcOffset)
const
137 QList<QByteArray> result;
138 if (
auto ids = allZoneIds(utcOffset)) {
139 result.reserve(ids->size());
140 for (std::string_view id : *ids)
141 result << QByteArray{id.data(), qsizetype(id.size())};
147QString QChronoTimeZonePrivate::abbreviation(qint64 atMSecsSinceEpoch)
const
149 if (
auto info = infoAtEpochMillis(m_timeZone, atMSecsSinceEpoch))
150 return fromSysInfo(*info, atMSecsSinceEpoch).abbreviation;
154int QChronoTimeZonePrivate::offsetFromUtc(qint64 atMSecsSinceEpoch)
const
156 if (
auto info = infoAtEpochMillis(m_timeZone, atMSecsSinceEpoch))
157 return fromSysInfo(*info, atMSecsSinceEpoch).offsetFromUtc;
158 return invalidSeconds();
161int QChronoTimeZonePrivate::standardTimeOffset(qint64 atMSecsSinceEpoch)
const
164 if (
auto info = infoAtEpochMillis(m_timeZone, atMSecsSinceEpoch))
165 return int((info->offset - info->save).count());
166 return invalidSeconds();
169int QChronoTimeZonePrivate::daylightTimeOffset(qint64 atMSecsSinceEpoch)
const
171 if (
auto info = infoAtEpochMillis(m_timeZone, atMSecsSinceEpoch))
172 return int(std::chrono::seconds(info->save).count());
173 return invalidSeconds();
176bool QChronoTimeZonePrivate::hasDaylightTime()
const
178 Data data = QTimeZonePrivate::data(QTimeZone::DaylightTime);
179 return data.daylightTimeOffset != 0
180 && data.daylightTimeOffset != invalidSeconds();
183bool QChronoTimeZonePrivate::isDaylightTime(qint64 atMSecsSinceEpoch)
const
185 if (
auto info = infoAtEpochMillis(m_timeZone, atMSecsSinceEpoch))
186 return info->save != 0min;
190QChronoTimeZonePrivate::Data
191QChronoTimeZonePrivate::data(qint64 forMSecsSinceEpoch)
const
193 if (
auto info = infoAtEpochMillis(m_timeZone, forMSecsSinceEpoch))
194 return fromSysInfo(*info, forMSecsSinceEpoch);
198bool QChronoTimeZonePrivate::hasTransitions()
const
203QChronoTimeZonePrivate::Data
204QChronoTimeZonePrivate::nextTransition(qint64 afterMSecsSinceEpoch)
const
206 if (
const auto info = infoAtEpochMillis(m_timeZone, afterMSecsSinceEpoch)) {
207 const auto tran = info->end;
208 qint64 when = milliseconds(tran.time_since_epoch()).count();
209 if (when > afterMSecsSinceEpoch)
210 return fromSysInfo(m_timeZone->get_info(tran), when);
216QChronoTimeZonePrivate::Data
217QChronoTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch)
const
219 if (
const auto info = infoAtEpochMillis(m_timeZone, beforeMSecsSinceEpoch - 1)) {
220 qint64 when = milliseconds(info->begin.time_since_epoch()).count();
221 if (when < beforeMSecsSinceEpoch)
222 return fromSysInfo(*info, when);
#define EXCEPTION_CHECKED(expression, fallback)
static const std::vector< std::string_view > getAllZoneIds(std::optional< int > offset=std::nullopt)
static const std::optional< std::vector< std::string_view > > allZoneIds(std::optional< int > offset=std::nullopt)
static std::chrono::sys_time< std::chrono::milliseconds > chronoForEpochMillis(qint64 millis)
static const std::chrono::time_zone * idToZone(std::string_view id)
static QChronoTimeZonePrivate::Data fromSysInfo(std::chrono::sys_info info, qint64 atMSecsSinceEpoch)
static std::optional< std::chrono::sys_info > infoAtEpochMillis(const std::chrono::time_zone *zone, qint64 millis)