Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/libraries/Common/src/Interop/Interop.TimeZoneInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,8 @@ internal static unsafe partial ResultCode GetTimeZoneDisplayName(

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_IanaIdToWindowsId", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial int IanaIdToWindowsId(string ianaId, char* windowsId, int windowsIdLength);

[LibraryImport(Libraries.GlobalizationNative, EntryPoint = "GlobalizationNative_GetCanonicalTimeZoneId", StringMarshalling = StringMarshalling.Utf16)]
internal static unsafe partial int GetCanonicalTimeZoneId(string timeZoneId, char* canonicalId, int canonicalIdLength);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,23 @@ public AndroidTzData()
return tzLookupIDs;
}

private static unsafe bool IsLegacyTimeZoneId(string timeZoneId)
{
const int TimeZoneIdLength = 64; // Arbitrarily large, to be safe.
char* buffer = stackalloc char[TimeZoneIdLength];

int canonicalIdLength = Interop.Globalization.GetCanonicalTimeZoneId(timeZoneId, buffer, TimeZoneIdLength);

if (canonicalIdLength <= 0)
{
return false; // If we can't get canonical ID, assume it's not legacy

}

ReadOnlySpan<char> canonicalIdSpan = new ReadOnlySpan<char>(buffer, canonicalIdLength);
return !timeZoneId.AsSpan().SequenceEqual(canonicalIdSpan);
}

[MemberNotNullWhen(true, nameof(_ids))]
[MemberNotNullWhen(true, nameof(_byteOffsets))]
[MemberNotNullWhen(true, nameof(_lengths))]
Expand Down Expand Up @@ -391,7 +408,13 @@ private void ReadIndex(string tzFileDir, Stream fs, int indexOffset, int dataOff
_ids[i] = id;
_lengths[i] = length;
if (tzLookupIDs != null)
{
_isBackwards[i] = !tzLookupIDs.Contains(id);
}
else
{
_isBackwards[i] = IsLegacyTimeZoneId(id);
}

if (length < 24) // Header Size
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ extern ucol_safeClone_func ucol_safeClone_ptr;
PER_FUNCTION_BLOCK(ucal_close, libicui18n, true) \
PER_FUNCTION_BLOCK(ucal_get, libicui18n, true) \
PER_FUNCTION_BLOCK(ucal_getAttribute, libicui18n, true) \
PER_FUNCTION_BLOCK(ucal_getCanonicalTimeZoneID, libicui18n, true) \
PER_FUNCTION_BLOCK(ucal_getKeywordValuesForLocale, libicui18n, true) \
PER_FUNCTION_BLOCK(ucal_getLimit, libicui18n, true) \
PER_FUNCTION_BLOCK(ucal_getNow, libicui18n, true) \
Expand Down Expand Up @@ -232,6 +233,7 @@ FOR_ALL_ICU_FUNCTIONS
#define ucal_close(...) ucal_close_ptr(__VA_ARGS__)
#define ucal_get(...) ucal_get_ptr(__VA_ARGS__)
#define ucal_getAttribute(...) ucal_getAttribute_ptr(__VA_ARGS__)
#define ucal_getCanonicalTimeZoneID(...) ucal_getCanonicalTimeZoneID_ptr(__VA_ARGS__)
#define ucal_getKeywordValuesForLocale(...) ucal_getKeywordValuesForLocale_ptr(__VA_ARGS__)
#define ucal_getLimit(...) ucal_getLimit_ptr(__VA_ARGS__)
#define ucal_getNow(...) ucal_getNow_ptr(__VA_ARGS__)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@ void ucal_add(UCalendar * cal, UCalendarDateFields field, int32_t amount, UError
void ucal_close(UCalendar * cal);
int32_t ucal_get(const UCalendar * cal, UCalendarDateFields field, UErrorCode * status);
int32_t ucal_getAttribute(const UCalendar * cal, UCalendarAttribute attr);
int32_t ucal_getCanonicalTimeZoneID(const UChar * id, int32_t len, UChar * result, int32_t resultCapacity, UBool * isSystemID, UErrorCode * status);
UEnumeration * ucal_getKeywordValuesForLocale(const char * key, const char * locale, UBool commonlyUsed, UErrorCode * status);
int32_t ucal_getLimit(const UCalendar * cal, UCalendarDateFields field, UCalendarLimitType type, UErrorCode * status);
UDate ucal_getNow(void);
Expand Down
18 changes: 18 additions & 0 deletions src/native/libs/System.Globalization.Native/pal_timeZoneInfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,21 @@ ResultCode GlobalizationNative_GetTimeZoneDisplayName(const UChar* localeName, c

return GetResultCode(err);
}

/*
Get the canonical timezone ID for a given timezone ID.
*/
int32_t GlobalizationNative_GetCanonicalTimeZoneId(const UChar* timeZoneId, UChar* canonicalId, int32_t canonicalIdLength)
{
UErrorCode status = U_ZERO_ERROR;
UBool isSystemID = 0;

int32_t actualLength = ucal_getCanonicalTimeZoneID(timeZoneId, -1, canonicalId, canonicalIdLength, &isSystemID, &status);

if (U_SUCCESS(status))
{
return actualLength;
}

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ typedef enum
PALEXPORT int32_t GlobalizationNative_WindowsIdToIanaId(const UChar* windowsId, const char* region, UChar* ianaId, int32_t ianaIdLength);
PALEXPORT int32_t GlobalizationNative_IanaIdToWindowsId(const UChar* ianaId, UChar* windowsId, int32_t windowsIdLength);
PALEXPORT ResultCode GlobalizationNative_GetTimeZoneDisplayName(const UChar* localeName, const UChar* timeZoneId, TimeZoneDisplayNameType type, UChar* result, int32_t resultLength);
PALEXPORT int32_t GlobalizationNative_GetCanonicalTimeZoneId(const UChar* timeZoneId, UChar* canonicalId, int32_t canonicalIdLength);
#if defined(APPLE_HYBRID_GLOBALIZATION)
PALEXPORT int32_t GlobalizationNative_GetTimeZoneDisplayNameNative(const uint16_t* localeName, int32_t lNameLength, const uint16_t* timeZoneId, int32_t timeZoneIdLength,
TimeZoneDisplayNameType type, uint16_t* result, int32_t resultLength);
Expand Down
Loading