在不使用字符串的情况下获取 javascript 中另一个时区的时区偏移量
get timezone offset of another timezone in javascript without using Strings
我想计算从 'users time' 到 'WET/WEST' 的偏移量。
我用新 Date().getTimezoneOffset()
得到用户偏移量。
但是如何获得 WET/WEST 的偏移量以便我可以计算两者的组合偏移量?
例如,如果用户使用中欧时间 (CET/CEST),则在冬季,组合偏移量将为 -60 (CET) + 0 (WET) = -60。在夏季,它将是 -120 (CEST) + 60 (WEST) = -60。在这种情况下,它始终为 -60,但用户也可以使用没有 DST 的时区。
如果不将其格式化为字符串并从该字符串中读出新时区,这是否可行?
您不能可靠地使用时区缩写进行输入,因为它们可以用许多不同的方式进行解释。例如,CST
在北美可能是 "Central Standard Time",或 "China Standard Time",或 "Cuba Standard Time"。虽然一些缩写如 WET
和 WEST
是唯一的,但许多缩写是模棱两可的。参考the list of time zone abbreviations here.
相反,您需要知道 IANA 时区标识符。一处 that uses WET/WEST is Portugal, which as the IANA identifier of "Europe/Lisbon"
. You can find a list of identifiers here。选择正确的标识符很重要,因为时区会随着时间而变化。每个标识符都反映了每个地区的特定历史。
如果您知道 IANA 时区标识符,那么您可以选择如何使用它:
在一些完全支持 ECMAScript Internationalization API (ECMA-402) 时区功能的现代浏览器中,您可以执行以下操作:
var d = new Date();
var s = d.toLocaleString(undefined, { timeZone: "Europe/Lisbon" })
这将在格式化期间将提供的日期和时间转换为正确的时区。在第一个参数中传递 undefined
将使用当前语言环境进行格式化。
这种方法有一些缺点,因为它尚未在所有浏览器中实现,并且没有 API 仅用于检索特定时间点的原始时区偏移量。
您可以考虑使用实现此功能的库。 I list several of them here. My personal preference is for moment.js with the moment-timezone 插件,您可以执行以下操作:
var m = moment.tz("Europe/Lisbon");
var s = m.format();
您可以将参数传递给 format
方法以根据需要显示输出。也可以转换一个已经存在的时间,比如:
var m = moment.utc("2016-01-01T00:00:00").tz("Europe/Lisbon");
var s = m.format();
您还可以像这样及时获取特定时刻的偏移量:
var m = moment.utc("2016-01-01T00:00:00").tz("Europe/Lisbon");
var offsetInMinutes = m.utcOffset();
var offsetAsString = m.format("Z");
您可以编写自己的代码来处理特定时区。虽然这很容易出错,但我一般不推荐这样做。如果沿着这条路走,更新可能会特别困难。
另请记住,特定时区的偏移量会根据生效的日期和时间而有所不同。因此,代表 "now" 的 new Date()
不一定总是正确的输入,具体取决于您的情况。
我想在不使用库的情况下执行此操作,因此我编写了这个函数,为您提供给定时区和 utc 之间的时区偏移量:
function getTimezoneOffsetFrom(otherTimezone) {
if (otherTimezone === void 0) { otherTimezone = "Europe/Amsterdam"; }
var date = new Date();
function objFromStr(str) {
var array = str.replace(":", " ").split(" ");
return {
day: parseInt(array[0]),
hour: parseInt(array[1]),
minute: parseInt(array[2])
};
}
var str = date.toLocaleString(['nl-NL'], { timeZone: otherTimezone, day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: false });
var other = objFromStr(str);
str = date.toLocaleString(['nl-NL'], { day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: false });
var myLocale = objFromStr(str);
var amsterdamOffset = (other.day * 24 * 60) + (other.hour * 60) + (other.minute);
var myLocaleOffset = (myLocale.day * 24 * 60) + (myLocale.hour * 60) + (myLocale.minute);
return myLocaleOffset - amsterdamOffset + date.getTimezoneOffset();
}
也许可以通过使用 en-US 作为语言环境字符串来批准,然后 str.replace 可能需要过滤逗号或其他内容。
我也想没有图书馆,但即使现在它有固定数量的时区数据,所以如果你不继续更新,30 年后就会中断,只是让我有点生气。虽然这确实使用了字符串,但没有什么比解析一个只是数字的字符串更复杂的了
function getTimezoneOffset(dt, timezone) {
let getItem = function(format) {
format.timeZone = timezone;
return parseInt(dt.toLocaleString(
'en-US', format));
};
let adjDate = new Date(
getItem({year: 'numeric'}),
getItem({month: 'numeric'}) - 1, // months are zero based
getItem({day: 'numeric'}),
getItem({hour: 'numeric',hour12: false}),
getItem({minute: 'numeric'}));
let noSecs = new Date(dt.getTime());
noSecs.setSeconds(0, 0);
let diff = Math.round((adjDate.getTime() - noSecs.getTime()) / 60000);
return dt.getTimezoneOffset() - diff;
}
我想计算从 'users time' 到 'WET/WEST' 的偏移量。
我用新 Date().getTimezoneOffset()
得到用户偏移量。
但是如何获得 WET/WEST 的偏移量以便我可以计算两者的组合偏移量?
例如,如果用户使用中欧时间 (CET/CEST),则在冬季,组合偏移量将为 -60 (CET) + 0 (WET) = -60。在夏季,它将是 -120 (CEST) + 60 (WEST) = -60。在这种情况下,它始终为 -60,但用户也可以使用没有 DST 的时区。
如果不将其格式化为字符串并从该字符串中读出新时区,这是否可行?
您不能可靠地使用时区缩写进行输入,因为它们可以用许多不同的方式进行解释。例如,CST
在北美可能是 "Central Standard Time",或 "China Standard Time",或 "Cuba Standard Time"。虽然一些缩写如 WET
和 WEST
是唯一的,但许多缩写是模棱两可的。参考the list of time zone abbreviations here.
相反,您需要知道 IANA 时区标识符。一处 that uses WET/WEST is Portugal, which as the IANA identifier of "Europe/Lisbon"
. You can find a list of identifiers here。选择正确的标识符很重要,因为时区会随着时间而变化。每个标识符都反映了每个地区的特定历史。
如果您知道 IANA 时区标识符,那么您可以选择如何使用它:
在一些完全支持 ECMAScript Internationalization API (ECMA-402) 时区功能的现代浏览器中,您可以执行以下操作:
var d = new Date(); var s = d.toLocaleString(undefined, { timeZone: "Europe/Lisbon" })
这将在格式化期间将提供的日期和时间转换为正确的时区。在第一个参数中传递
undefined
将使用当前语言环境进行格式化。这种方法有一些缺点,因为它尚未在所有浏览器中实现,并且没有 API 仅用于检索特定时间点的原始时区偏移量。
您可以考虑使用实现此功能的库。 I list several of them here. My personal preference is for moment.js with the moment-timezone 插件,您可以执行以下操作:
var m = moment.tz("Europe/Lisbon"); var s = m.format();
您可以将参数传递给
format
方法以根据需要显示输出。也可以转换一个已经存在的时间,比如:var m = moment.utc("2016-01-01T00:00:00").tz("Europe/Lisbon"); var s = m.format();
您还可以像这样及时获取特定时刻的偏移量:
var m = moment.utc("2016-01-01T00:00:00").tz("Europe/Lisbon"); var offsetInMinutes = m.utcOffset(); var offsetAsString = m.format("Z");
您可以编写自己的代码来处理特定时区。虽然这很容易出错,但我一般不推荐这样做。如果沿着这条路走,更新可能会特别困难。
另请记住,特定时区的偏移量会根据生效的日期和时间而有所不同。因此,代表 "now" 的 new Date()
不一定总是正确的输入,具体取决于您的情况。
我想在不使用库的情况下执行此操作,因此我编写了这个函数,为您提供给定时区和 utc 之间的时区偏移量:
function getTimezoneOffsetFrom(otherTimezone) {
if (otherTimezone === void 0) { otherTimezone = "Europe/Amsterdam"; }
var date = new Date();
function objFromStr(str) {
var array = str.replace(":", " ").split(" ");
return {
day: parseInt(array[0]),
hour: parseInt(array[1]),
minute: parseInt(array[2])
};
}
var str = date.toLocaleString(['nl-NL'], { timeZone: otherTimezone, day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: false });
var other = objFromStr(str);
str = date.toLocaleString(['nl-NL'], { day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: false });
var myLocale = objFromStr(str);
var amsterdamOffset = (other.day * 24 * 60) + (other.hour * 60) + (other.minute);
var myLocaleOffset = (myLocale.day * 24 * 60) + (myLocale.hour * 60) + (myLocale.minute);
return myLocaleOffset - amsterdamOffset + date.getTimezoneOffset();
}
也许可以通过使用 en-US 作为语言环境字符串来批准,然后 str.replace 可能需要过滤逗号或其他内容。
我也想没有图书馆,但即使现在它有固定数量的时区数据,所以如果你不继续更新,30 年后就会中断,只是让我有点生气。虽然这确实使用了字符串,但没有什么比解析一个只是数字的字符串更复杂的了
function getTimezoneOffset(dt, timezone) {
let getItem = function(format) {
format.timeZone = timezone;
return parseInt(dt.toLocaleString(
'en-US', format));
};
let adjDate = new Date(
getItem({year: 'numeric'}),
getItem({month: 'numeric'}) - 1, // months are zero based
getItem({day: 'numeric'}),
getItem({hour: 'numeric',hour12: false}),
getItem({minute: 'numeric'}));
let noSecs = new Date(dt.getTime());
noSecs.setSeconds(0, 0);
let diff = Math.round((adjDate.getTime() - noSecs.getTime()) / 60000);
return dt.getTimezoneOffset() - diff;
}