1044std::optional<Vector<UChar, 32>> isTimeZoneValid(const String& timeZone)
1045{
1046 // Timezone is ascii.
1047 Vector<UChar> buffer(timeZone.length());
1048 UChar* bufferStart = buffer.data();
1049 CString ctz = timeZone.utf8();
1050 if (!Unicode::convertUTF8ToUTF16(ctz.data(), ctz.data() + ctz.length(), &bufferStart, bufferStart + timeZone.length()))
1051 return std::nullopt;
1052
1053 Vector<UChar, 32> canonicalBuffer(32);
1054 UErrorCode status = U_ZERO_ERROR;
1055 auto canonicalLength = ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalBuffer.size(), nullptr, &status);
1056 if (status == U_BUFFER_OVERFLOW_ERROR) {
1057 status = U_ZERO_ERROR;
1058 canonicalBuffer.grow(canonicalLength);
1059 ucal_getCanonicalTimeZoneID(buffer.data(), buffer.size(), canonicalBuffer.data(), canonicalLength, nullptr, &status);
1060 } else
1061 canonicalBuffer.resize(canonicalLength);
1062 return canonicalBuffer;
1063}
1064
1065bool setTimeZoneOverride(const String& timeZone)
1066{
1067 innerTimeZoneOverride().displayName = String();
1068 if (innerTimeZoneOverride().cal) {
1069 ucal_close(innerTimeZoneOverride().cal);
1070 innerTimeZoneOverride().cal = nullptr;
1071 }
1072
1073 if (timeZone.isEmpty()) {
1074 innerTimeZoneOverride().id = String();
1075 return true;
1076 }
1077
1078 auto canonicalBuffer = isTimeZoneValid(timeZone);
1079 if (!canonicalBuffer)
1080 return false;
1081
1082 auto canonicalLength = canonicalBuffer->size();
1083 UErrorCode status = U_ZERO_ERROR;
1084 UCalendar* cal = ucal_open(canonicalBuffer->data(), canonicalLength, nullptr, UCAL_TRADITIONAL, &status);
1085 if (!U_SUCCESS(status))
1086 return false;
1087
1088 Vector<UChar, 32> displayNameBuffer(32);
1089 auto displayNameLength = ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameBuffer.size(), &status);
1090 if (status == U_BUFFER_OVERFLOW_ERROR) {
1091 status = U_ZERO_ERROR;
1092 displayNameBuffer.grow(displayNameLength);
1093 ucal_getTimeZoneDisplayName(cal, UCAL_STANDARD, defaultLanguage().utf8().data(), displayNameBuffer.data(), displayNameLength, &status);
1094 }
1095 if (!U_SUCCESS(status))
1096 return false;
1097
1098 auto& timeZoneOverride = innerTimeZoneOverride();
1099 timeZoneOverride.cal = cal;
1100 timeZoneOverride.id = String(canonicalBuffer->data(), canonicalLength);
1101 timeZoneOverride.displayName = String(displayNameBuffer.data(), displayNameLength);
1102 return true;
1103}
1104
1105String& timeZoneOverride()
1106{
1107 return innerTimeZoneOverride().id;
1108}
1109
1110String& timeZoneDisplayNameOverride()
1111{
1112 return innerTimeZoneOverride().displayName;
1113}
1114