在不使用字符串表示的情况下创建具有设置时区的日期

IT技术 javascript timezone
2021-01-31 12:34:54

我有一个包含日、月和年三个下拉菜单的网页。如果我使用Date带数字的 JavaScript构造函数,那么我会得到一个Date当前时区对象:

new Date(xiYear, xiMonth, xiDate)

给出正确的日期,但由于夏令时,它认为该日期是 GMT+01:00。

这里的问题是,我然后将其传递Date给 Ajax 方法,当日期在服务器上反序列化时,它已转换为 GMT,因此丢失了一个小时,将日期向后移动一个小时。现在我可以将日、月和年单独传递到 Ajax 方法中,但似乎应该有更好的方法。

接受的答案为我指明了正确的方向,但是仅使用setUTCHours()本身就发生了变化:

Apr 5th 00:00 GMT+01:00 

Apr 4th 23:00 GMT+01:00

然后我还必须设置 UTC 日期、月份和年份以结束

Apr 5th 01:00 GMT+01:00

这就是我想要的。

6个回答

使用.setUTCHours()它可以在 UTC 时间中实际设置日期,这将允许您在整个系统中使用 UTC 时间。

但是,除非您指定日期字符串,否则您不能在构造函数中使用 UTC 设置它。

使用new Date(Date.UTC(year, month, day, hour, minute, second))您可以从特定的 UTC 时间创建日期对象。

请记住,当使用“日期”时,“月”值的范围是 0-11(不是 1-12)。我一直得到 2 小时的时区偏移(虽然它应该是 1 小时),但我花了几个小时才发现原因是错误的月份。
2021-03-14 12:34:54
@jishi - 日期对象基于 UTC 时间值,而不是本地时间。但是,默认的Date.prototype.toString方法将显示本地时间值。
2021-03-16 12:34:54
@Anthony——“但不是同一时间”是不正确的。它代表完全相同的时刻,唯一的区别是时区偏移。
2021-03-18 12:34:54
“new Date(Date.UTC(...))”语法允许您创建一个日期,该日期就其代表的时间点而言等同于 UTC 日期,但它并不相同——它有一个不同(非 UTC)时区。
2021-03-22 12:34:54
这个答案很棒。但是我正在使用一个库 [datepicker ui],它在很多地方都使用了 new Date。我想要的只是设置 UTC 时区,每个日期都按照新时区。我很惊讶 Javascript 对此没有任何帮助。
2021-03-31 12:34:54
var d = new Date(xiYear, xiMonth, xiDate);
d.setTime( d.getTime() + d.getTimezoneOffset()*60*1000 );

此答案是专门针对原始问题量身定制的,不会给出您所期望的答案。特别是,有些人会想要减去时区偏移量而不是添加它。请记住,尽管此解决方案的重点是为特定的反序列化破解 javascript 的日期对象,但并非在所有情况下都是正确的。

是的,正如其他人指出的那样 - 我认为这个答案有误。应该是减号而不是加号。
2021-03-10 12:34:54
如果您将 timezoneOffset 添加到日期对象,其在本地时区中格式化的值将看起来像 UTC 中的正确值,但它仍将具有原始时区偏移量(并且诸如“ISOString”之类的某些表示实际上会显示它)。因此,根据您随后如何序列化日期对象,JS 可能会再次应用时区偏移量,从而给您错误的答案。我相信这是造成 +/- 之间这些评论混淆的原因。无论如何,我的反对票是为了这个事实,也是为了“在大多数情况下你会得到你所期望的”。
2021-03-12 12:34:54
这几乎对我有用,除了我必须使用 - (减号)而不是 + (加号)来为我的时区获取正确的时间。
2021-04-01 12:34:54
@gthmb 当然,但我觉得*60*1000在这种情况下更清楚;换句话说,它为什么在那里是不言而喻的。
2021-04-04 12:34:54
根据developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... getTimezoneOffset 返回的值根据您调用该函数时您所在地区的实际偏移量进行签名,包括考虑 DST,所以我不明白为什么你需要减去它。
2021-04-05 12:34:54

我相信您需要createDateAsUTC函数(请与convertDateToUTC进行比较

function createDateAsUTC(date) {
    return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()));
}

function convertDateToUTC(date) { 
    return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()); 
}
我现在明白了:第一个返回 UTC 时区中的日期,以及本地时间的文字日期值。第二个返回本地时区中的日期,但使用 UTC 文字日期值。
2021-03-16 12:34:54
我对他的回答清晰和乐于助人感到惊讶。直到今天才知道使用 Javascript 日期是一场噩梦:S
2021-03-29 12:34:54
介意解释一下两者之间的区别吗?第一个转换date为 UTC 时区,但第二个似乎没有任何用处?(返回与 相同的日期date
2021-04-07 12:34:54
它还可能导致时间值错误,接近本地时区的夏令时转换。简而言之,时代转换(通过任何实现)不适用于 JavaScriptDate对象。在这里看到的另一种方法是Date.UTC期望基于 UTC 的值,并且您正在为其提供本地时间值,反之亦然与Date构造函数。
2021-04-08 12:34:54
这种方法是一种称为“纪元转移”的模式的实现,旨在将纪元(即基于 UTC)移动到由当前时区偏移量偏移的纪元。不幸的是,尽管这很常见,但这种方法是有缺陷的。JavaScript 的Date对象将始终反映基于 UTC 的 unix 纪元和本地时区。当您调用toString生成的日期对象并仍然看到本地时区时,即使您希望它使用 UTC,该症状也很明显
2021-04-09 12:34:54

只需设置时区并返回

new Date().toLocaleString("en-US", {timeZone: "America/New_York"})

其他时区如下

var world_timezones =
[
    'Europe/Andorra',
    'Asia/Dubai',
    'Asia/Kabul',
    'Europe/Tirane',
    'Asia/Yerevan',
    'Antarctica/Casey',
    'Antarctica/Davis',
    'Antarctica/DumontDUrville', 
    'Antarctica/Mawson',
    'Antarctica/Palmer',
    'Antarctica/Rothera',
    'Antarctica/Syowa',
    'Antarctica/Troll',
    'Antarctica/Vostok',
    'America/Argentina/Buenos_Aires',
    'America/Argentina/Cordoba',
    'America/Argentina/Salta',
    'America/Argentina/Jujuy',
    'America/Argentina/Tucuman',
    'America/Argentina/Catamarca',
    'America/Argentina/La_Rioja',
    'America/Argentina/San_Juan',
    'America/Argentina/Mendoza',
    'America/Argentina/San_Luis',
    'America/Argentina/Rio_Gallegos',
    'America/Argentina/Ushuaia',
    'Pacific/Pago_Pago',
    'Europe/Vienna',
    'Australia/Lord_Howe',
    'Antarctica/Macquarie',
    'Australia/Hobart',
    'Australia/Currie',
    'Australia/Melbourne',
    'Australia/Sydney',
    'Australia/Broken_Hill',
    'Australia/Brisbane',
    'Australia/Lindeman',
    'Australia/Adelaide',
    'Australia/Darwin',
    'Australia/Perth',
    'Australia/Eucla',
    'Asia/Baku',
    'America/Barbados',
    'Asia/Dhaka',
    'Europe/Brussels',
    'Europe/Sofia',
    'Atlantic/Bermuda',
    'Asia/Brunei',
    'America/La_Paz',
    'America/Noronha',
    'America/Belem',
    'America/Fortaleza',
    'America/Recife',
    'America/Araguaina',
    'America/Maceio',
    'America/Bahia',
    'America/Sao_Paulo',
    'America/Campo_Grande',
    'America/Cuiaba',
    'America/Santarem',
    'America/Porto_Velho',
    'America/Boa_Vista',
    'America/Manaus',
    'America/Eirunepe',
    'America/Rio_Branco',
    'America/Nassau',
    'Asia/Thimphu',
    'Europe/Minsk',
    'America/Belize',
    'America/St_Johns',
    'America/Halifax',
    'America/Glace_Bay',
    'America/Moncton',
    'America/Goose_Bay',
    'America/Blanc-Sablon',
    'America/Toronto',
    'America/Nipigon',
    'America/Thunder_Bay',
    'America/Iqaluit',
    'America/Pangnirtung',
    'America/Atikokan',
    'America/Winnipeg',
    'America/Rainy_River',
    'America/Resolute',
    'America/Rankin_Inlet',
    'America/Regina',
    'America/Swift_Current',
    'America/Edmonton',
    'America/Cambridge_Bay',
    'America/Yellowknife',
    'America/Inuvik',
    'America/Creston',
    'America/Dawson_Creek',
    'America/Fort_Nelson',
    'America/Vancouver',
    'America/Whitehorse',
    'America/Dawson',
    'Indian/Cocos',
    'Europe/Zurich',
    'Africa/Abidjan',
    'Pacific/Rarotonga',
    'America/Santiago',
    'America/Punta_Arenas',
    'Pacific/Easter',
    'Asia/Shanghai',
    'Asia/Urumqi',
    'America/Bogota',
    'America/Costa_Rica',
    'America/Havana',
    'Atlantic/Cape_Verde',
    'America/Curacao',
    'Indian/Christmas',
    'Asia/Nicosia',
    'Asia/Famagusta',
    'Europe/Prague',
    'Europe/Berlin',
    'Europe/Copenhagen',
    'America/Santo_Domingo',
    'Africa/Algiers',
    'America/Guayaquil',
    'Pacific/Galapagos',
    'Europe/Tallinn',
    'Africa/Cairo',
    'Africa/El_Aaiun',
    'Europe/Madrid',
    'Africa/Ceuta',
    'Atlantic/Canary',
    'Europe/Helsinki',
    'Pacific/Fiji',
    'Atlantic/Stanley',
    'Pacific/Chuuk',
    'Pacific/Pohnpei',
    'Pacific/Kosrae',
    'Atlantic/Faroe',
    'Europe/Paris',
    'Europe/London',
    'Asia/Tbilisi',
    'America/Cayenne',
    'Africa/Accra',
    'Europe/Gibraltar',
    'America/Godthab',
    'America/Danmarkshavn',
    'America/Scoresbysund',
    'America/Thule',
    'Europe/Athens',
    'Atlantic/South_Georgia',
    'America/Guatemala',
    'Pacific/Guam',
    'Africa/Bissau',
    'America/Guyana',
    'Asia/Hong_Kong',
    'America/Tegucigalpa',
    'America/Port-au-Prince',
    'Europe/Budapest',
    'Asia/Jakarta',
    'Asia/Pontianak',
    'Asia/Makassar',
    'Asia/Jayapura',
    'Europe/Dublin',
    'Asia/Jerusalem',
    'Asia/Kolkata',
    'Indian/Chagos',
    'Asia/Baghdad',
    'Asia/Tehran',
    'Atlantic/Reykjavik',
    'Europe/Rome',
    'America/Jamaica',
    'Asia/Amman',
    'Asia/Tokyo',
    'Africa/Nairobi',
    'Asia/Bishkek',
    'Pacific/Tarawa',
    'Pacific/Enderbury',
    'Pacific/Kiritimati',
    'Asia/Pyongyang',
    'Asia/Seoul',
    'Asia/Almaty',
    'Asia/Qyzylorda',
    'Asia/Qostanay', 
    'Asia/Aqtobe',
    'Asia/Aqtau',
    'Asia/Atyrau',
    'Asia/Oral',
    'Asia/Beirut',
    'Asia/Colombo',
    'Africa/Monrovia',
    'Europe/Vilnius',
    'Europe/Luxembourg',
    'Europe/Riga',
    'Africa/Tripoli',
    'Africa/Casablanca',
    'Europe/Monaco',
    'Europe/Chisinau',
    'Pacific/Majuro',
    'Pacific/Kwajalein',
    'Asia/Yangon',
    'Asia/Ulaanbaatar',
    'Asia/Hovd',
    'Asia/Choibalsan',
    'Asia/Macau',
    'America/Martinique',
    'Europe/Malta',
    'Indian/Mauritius',
    'Indian/Maldives',
    'America/Mexico_City',
    'America/Cancun',
    'America/Merida',
    'America/Monterrey',
    'America/Matamoros',
    'America/Mazatlan',
    'America/Chihuahua',
    'America/Ojinaga',
    'America/Hermosillo',
    'America/Tijuana',
    'America/Bahia_Banderas',
    'Asia/Kuala_Lumpur',
    'Asia/Kuching',
    'Africa/Maputo',
    'Africa/Windhoek',
    'Pacific/Noumea',
    'Pacific/Norfolk',
    'Africa/Lagos',
    'America/Managua',
    'Europe/Amsterdam',
    'Europe/Oslo',
    'Asia/Kathmandu',
    'Pacific/Nauru',
    'Pacific/Niue',
    'Pacific/Auckland',
    'Pacific/Chatham',
    'America/Panama',
    'America/Lima',
    'Pacific/Tahiti',
    'Pacific/Marquesas',
    'Pacific/Gambier',
    'Pacific/Port_Moresby',
    'Pacific/Bougainville',
    'Asia/Manila',
    'Asia/Karachi',
    'Europe/Warsaw',
    'America/Miquelon',
    'Pacific/Pitcairn',
    'America/Puerto_Rico',
    'Asia/Gaza',
    'Asia/Hebron',
    'Europe/Lisbon',
    'Atlantic/Madeira',
    'Atlantic/Azores',
    'Pacific/Palau',
    'America/Asuncion',
    'Asia/Qatar',
    'Indian/Reunion',
    'Europe/Bucharest',
    'Europe/Belgrade',
    'Europe/Kaliningrad',
    'Europe/Moscow',
    'Europe/Simferopol',
    'Europe/Kirov',
    'Europe/Astrakhan',
    'Europe/Volgograd',
    'Europe/Saratov',
    'Europe/Ulyanovsk',
    'Europe/Samara',
    'Asia/Yekaterinburg',
    'Asia/Omsk',
    'Asia/Novosibirsk',
    'Asia/Barnaul',
    'Asia/Tomsk',
    'Asia/Novokuznetsk',
    'Asia/Krasnoyarsk',
    'Asia/Irkutsk',
    'Asia/Chita',
    'Asia/Yakutsk',
    'Asia/Khandyga',
    'Asia/Vladivostok',
    'Asia/Ust-Nera',
    'Asia/Magadan',
    'Asia/Sakhalin',
    'Asia/Srednekolymsk',
    'Asia/Kamchatka',
    'Asia/Anadyr',
    'Asia/Riyadh',
    'Pacific/Guadalcanal',
    'Indian/Mahe',
    'Africa/Khartoum',
    'Europe/Stockholm',
    'Asia/Singapore',
    'America/Paramaribo',
    'Africa/Juba',
    'Africa/Sao_Tome',
    'America/El_Salvador',
    'Asia/Damascus',
    'America/Grand_Turk',
    'Africa/Ndjamena',
    'Indian/Kerguelen',
    'Asia/Bangkok',
    'Asia/Dushanbe',
    'Pacific/Fakaofo',
    'Asia/Dili',
    'Asia/Ashgabat',
    'Africa/Tunis',
    'Pacific/Tongatapu',
    'Europe/Istanbul',
    'America/Port_of_Spain',
    'Pacific/Funafuti',
    'Asia/Taipei',
    'Europe/Kiev',
    'Europe/Uzhgorod',
    'Europe/Zaporozhye',
    'Pacific/Wake',
    'America/New_York',
    'America/Detroit',
    'America/Kentucky/Louisville',
    'America/Kentucky/Monticello',
    'America/Indiana/Indianapolis',
    'America/Indiana/Vincennes',
    'America/Indiana/Winamac',
    'America/Indiana/Marengo',
    'America/Indiana/Petersburg',
    'America/Indiana/Vevay',
    'America/Chicago',
    'America/Indiana/Tell_City',
    'America/Indiana/Knox',
    'America/Menominee',
    'America/North_Dakota/Center',
    'America/North_Dakota/New_Salem',
    'America/North_Dakota/Beulah',
    'America/Denver',
    'America/Boise',
    'America/Phoenix',
    'America/Los_Angeles',
    'America/Anchorage',
    'America/Juneau',
    'America/Sitka',
    'America/Metlakatla',
    'America/Yakutat',
    'America/Nome',
    'America/Adak',
    'Pacific/Honolulu',
    'America/Montevideo',
    'Asia/Samarkand',
    'Asia/Tashkent',
    'America/Caracas',
    'Asia/Ho_Chi_Minh',
    'Pacific/Efate',
    'Pacific/Wallis',
    'Pacific/Apia',
    'Africa/Johannesburg'
];
但请注意,这在某些浏览器中不起作用。例如。IE11。
2021-03-20 12:34:54
IE 控制台中的错误: “timeZone”的选项值“AMERICA/NEW_YORK”超出有效范围。预期:['UTC'] @OloghoCyrilPaul
2021-03-20 12:34:54
非常轻松,非常优雅。您可以在此处找到包含所有时区的列表stackoverflow.com/questions/38399465/...对于 UTC,请选择伦敦时区。
2021-03-23 12:34:54
这应该在顶部
2021-03-31 12:34:54
这些值都不是“时区”,它们是具有相同历史本地时区和夏令时更改的地方的IANA 时区数据库代表位置。
2021-04-08 12:34:54

我不相信这是可能的 - 无法在创建 Date 对象后设置时区。

从某种意义上说,这是有道理的——从概念上讲(如果可能不在实施中);每个http://en.wikipedia.org/wiki/Unix_timestamp(强调我的):

Unix 时间或 POSIX 时间是一种用于描述时间瞬间的系统,定义为自1970 年 1 月 1 日星期四的协调世界时 (UTC)午夜以来经过的秒数

一旦你构建了一个,它将代表“实时”的某个点。时区仅在您想将该抽象时间点转换为人类可读的字符串时才相关。

因此,您只能更改 Date 在构造函数中表示的实际时间,这是有道理的。可悲的是,似乎没有办法传入一个明确的时区 - 你正在调用的构造函数(可以说是正确的)在它规范地存储它们时将你的“本地”时间变量转换为 GMT - 所以没有办法使用int, int, int构造函数格林威治标准时间。

从好的方面来说,只使用带有 String 的构造函数是微不足道的。您甚至不必将数字月份转换为字符串(至少在 Firefox 上),所以我希望一个简单的实现可以工作。但是,在尝试之后,它在 Firefox、Chrome 和 Opera 中成功运行,但在 Konqueror(“无效日期”)、Safari(“无效日期”)和 IE(“NaN”)中失败。我想你只有一个查找数组来将月份转换为字符串,如下所示:

var months = [ '', 'January', 'February', ..., 'December'];

function createGMTDate(xiYear, xiMonth, xiDate) {
   return new Date(months[xiMonth] + ' ' + xiDate + ', ' + xiYear + ' 00:00:00 GMT');
}
如果没有办法“Date对象上设置的时区创建后”,是不是在暗示,有一个方法来设置Date对象的时区创建它?它看起来不像一个 js 日期是“自 Epoch 以来围绕几秒钟的薄包装” - 它看起来像是秒数,加上一个时区。
2021-03-17 12:34:54
@Anthony,它只能使用客户端的时区。Javascript 可以在 utc 和 back 之间执行本地操作,但无法访问时区数据库。例如,当您在圣地亚哥时,它无法告诉您墨西哥城的时间。
2021-04-03 12:34:54