fixed: time zone methods return nil in Chrome and Firefox

This commit is contained in:
daboe01 committed 2025-06-22 19:27:58 +02:00
1 parent 85f7125f22
commit db51d5ca54
1 file changed
+58 -7
+58 -7
View File
@@ -25,6 +25,7 @@
@import "CPLocale.j"
@class CPData
@class CPNotificationCenter
CPTimeZoneNameStyleStandard = 0;
CPTimeZoneNameStyleShortStandard = 1;
@@ -46,13 +47,63 @@ var abbreviationDictionary,
function abbreviationForDate(date)
{
// Sometimes the browsers will give unmatched timezones in other languages so try one more thing
// Take the locale string for english in the US. It has the following format (9/21/2021, 2:40:44 PM Central European Summer Time)
// Remove the date and time with this regex and take first letter in each word in the time zone name.
// This is not 100% but is better than nothing as JAvascript has no good support for this.
var abbreviation = date.toLocaleString('en-US', {timeZoneName : 'long'}).replace(/^([0]?\d|[1][0-2])\/((?:[0]?|[1-2])\d|[3][0-1])\/([2][01]|[1][6-9])\d{2}(,?\s*([0]?\d|[1][0-2])(\:[0-5]\d){1,2})*\s*([aApP][mM]{0,2})?\s*/, "").split(" ").map(function(l) { return l[0]}).join("");
// Strategy 1: Parse date.toString() as it's more reliable than toLocaleString.
// Format is usually: "Day Mon dd yyyy hh:mm:ss GMT+XXXX (Time Zone Name)"
var dateString = date.toString();
return abbreviation;
// Check for a long name within parentheses, e.g., (Pacific Daylight Time)
var longNameMatch = dateString.match(/\(([^)]+)\)/);
if (longNameMatch) {
var timeZoneComponent = longNameMatch[1];
// If the component is already a known abbreviation (e.g., "EST"), return it.
if ([abbreviationDictionary objectForKey:timeZoneComponent]) {
return timeZoneComponent;
}
// If it's a long name (e.g., "Eastern Daylight Time"), create an acronym.
if (timeZoneComponent.indexOf(' ') > -1) {
var generatedAbbr = timeZoneComponent.split(' ').map(function(word) { return word[0]; }).join('');
if ([abbreviationDictionary objectForKey:generatedAbbr]) {
return generatedAbbr;
}
}
}
// Strategy 2: If string parsing fails (e.g., for "GMT-04:00"), use the modern and reliable Intl API.
try {
var ianaName = new Intl.DateTimeFormat().resolvedOptions().timeZone;
var currentOffset = -date.getTimezoneOffset(); // in minutes
var keys = [abbreviationDictionary keyEnumerator],
key;
// Find all abbreviations for the current IANA time zone.
var possibleAbbrs = [];
while (key = [keys nextObject]) {
if ([abbreviationDictionary valueForKey:key] === ianaName) {
possibleAbbrs.push(key);
}
}
// If more than one (e.g., standard and daylight), use the current offset to find the right one.
for (var i = 0; i < possibleAbbrs.length; i++) {
var abbr = possibleAbbrs[i];
if ([timeDifferenceFromUTC valueForKey:abbr] === currentOffset) {
return abbr;
}
}
// If offset matching fails but we have a unique IANA match, use it as a best guess.
if (possibleAbbrs.length > 0) {
return possibleAbbrs[0];
}
} catch (e) {
// Intl API not supported, or it failed. We cannot proceed with this strategy.
}
// Return nil if no valid abbreviation could be determined.
return nil;
}
/*!
@class CPTimeZone
@@ -445,7 +496,7 @@ function abbreviationForDate(date)
systemTimeZone = [self timeZoneWithAbbreviation:abbreviation];
[[CPNotification defaultCenter] postNotificationName:CPSystemTimeZoneDidChangeNotification object:systemTimeZone];
[[CPNotificationCenter defaultCenter] postNotificationName:CPSystemTimeZoneDidChangeNotification object:systemTimeZone];
}
/*! Return the systemTimeZone