Tạo một ngày với múi giờ đã đặt mà không cần sử dụng biểu diễn chuỗi


412

Tôi có một trang web với ba lần thả xuống cho ngày, tháng và năm. Nếu tôi sử dụng hàm tạo JavaScript Datelấy số, thì tôi nhận được một Dateđối tượng cho múi giờ hiện tại của mình:

new Date(xiYear, xiMonth, xiDate)

Đưa ra ngày chính xác, nhưng nó nghĩ rằng ngày đó là GMT + 01: 00 do thời gian tiết kiệm ánh sáng ban ngày.

Vấn đề ở đây là sau đó tôi chuyển Datephương thức này sang phương thức Ajax và khi ngày được khử lưu trữ trên máy chủ, nó đã được chuyển đổi thành GMT và do đó mất một giờ để di chuyển ngày trở lại. Bây giờ tôi chỉ có thể chuyển từng ngày, tháng và năm vào phương thức Ajax, nhưng có vẻ như phải có một cách tốt hơn.

Câu trả lời được chấp nhận đã chỉ cho tôi đi đúng hướng, tuy nhiên chỉ cần sử dụng setUTCHours()chính nó đã thay đổi:

Apr 5th 00:00 GMT+01:00 

đến

Apr 4th 23:00 GMT+01:00

Sau đó tôi cũng phải đặt ngày, tháng và năm để kết thúc với

Apr 5th 01:00 GMT+01:00

đó là những gì tôi muốn


9
Nếu câu trả lời được chấp nhận chỉ cho bạn đi đúng hướng nhưng không trả lời câu hỏi của bạn, tôi sẽ cho rằng đó không phải là câu trả lời được chấp nhận. Câu trả lời nên trả lời câu hỏi.
TWR Cole

Câu trả lời:


481

sử dụng .setUTCHours()nó có thể thực sự đặt ngày theo giờ UTC, điều này cho phép bạn sử dụng thời gian UTC trên toàn hệ thống.

Mặc dù vậy, bạn không thể đặt nó bằng UTC trong hàm tạo, trừ khi bạn chỉ định chuỗi ngày.

Sử dụng new Date(Date.UTC(year, month, day, hour, minute, second))bạn có thể tạo Đối tượng ngày từ thời gian UTC cụ thể.


101
Cú pháp "Ngày mới (Date.UTC (...))" cho phép bạn tạo một ngày tương đương với ngày UTC theo thời điểm mà nó thể hiện, nhưng nó không giống nhau - nó có một múi giờ khác nhau (không phải UTC).
Anthony

52
Hãy nhớ rằng khi sử dụng "Ngày", giá trị "tháng" có phạm vi từ 0-11 (không phải 1-12). Tôi liên tục nhận được thời gian bù 2 giờ (trong khi đáng lẽ là 1h) và tôi phải mất hàng giờ để biết rằng lý do là một tháng sai.
Chọn0r

4
Câu trả lời này là tuyệt vời. Nhưng tôi đang sử dụng một thư viện [datepicker ui] đang sử dụng Ngày mới ở nhiều nơi. Tất cả những gì tôi muốn là đặt múi giờ UTC và mỗi ngày là theo múi giờ mới. Tôi ngạc nhiên khi Javascript không có gì cho việc này.
Sanjeev Kumar Dangi

6
Các đối tượng @ jishi Ngày được dựa trên giá trị thời gian UTC, không phải giờ địa phương. Tuy nhiên, phương thức Date.prototype.toString mặc định sẽ hiển thị các giá trị thời gian cục bộ.
RobG

5
@ Anthony 59 " nhưng nó không phải là cùng một lúc " là không chính xác. Nó đại diện chính xác cùng một thời điểm, sự khác biệt duy nhất là bù múi giờ.
RobG

198
var d = new Date(xiYear, xiMonth, xiDate);
d.setTime( d.getTime() + d.getTimezoneOffset()*60*1000 );

Câu trả lời này được thiết kế riêng cho câu hỏi ban đầu và sẽ không đưa ra câu trả lời mà bạn nhất thiết mong đợi. Cụ thể, một số người sẽ muốn trừ phần bù múi giờ thay vì thêm nó. Mặc dù vậy, hãy nhớ rằng toàn bộ quan điểm của giải pháp này là hack đối tượng ngày của javascript để khử lưu lượng cụ thể, không chính xác trong mọi trường hợp.


62
@gthmb tất nhiên, nhưng tôi cảm thấy *60*1000rõ ràng hơn trong trường hợp này; nói cách khác, nó khá rõ ràng tại sao nó ở đó.
TWR Cole

22
Điều này gần như làm việc với tôi, ngoại trừ tôi phải sử dụng - (trừ) thay vì + (cộng) để có thời gian phù hợp với múi giờ của tôi.
Wytze

3
Vâng, như những người khác đã chỉ ra - Tôi nghĩ rằng có một sai lầm trong câu trả lời này. Nên trừ không cộng.
UpTheCux

3
Theo developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ , giá trị được trả về bởi getTimezone Offerset được ký theo phần bù thực tế tại địa phương của bạn tại thời điểm bạn gọi hàm, bao gồm cả đưa DST vào tài khoản, vì vậy tôi không hiểu tại sao bạn cần phải trừ nó.
TWR Cole

15
Nếu bạn thêm múi giờ vào đối tượng ngày, giá trị của nó như được định dạng trong múi giờ cục bộ sẽ trông giống như giá trị chính xác trong UTC, nhưng nó vẫn có phần bù múi giờ ban đầu (và một số biểu diễn như "ISOString" sẽ thực sự hiển thị nó). Vì vậy, tùy thuộc vào cách bạn sau đó tuần tự hóa đối tượng ngày, JS có thể áp dụng bù thời gian một lần nữa , cho bạn câu trả lời sai. Tôi tin rằng điều này chịu trách nhiệm cho sự nhầm lẫn trong các nhận xét giữa +/-. Dù sao, downvote của tôi là cho thực tế này và cũng cho "trong hầu hết các trường hợp bạn nhận được những gì bạn mong đợi".
metamatt

173

Tôi tin rằng bạn cần createDateAsUTC function (hãy so sánh với 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()); 
}

36
Tôi ngạc nhiên về câu trả lời rõ ràng và hữu ích của mình. Không biết rằng làm việc với ngày Javascript là một cơn ác mộng cho đến ngày hôm nay: S
will824

Tâm giải thích sự khác biệt giữa hai người? Cái đầu tiên chuyển datethành múi giờ UTC, nhưng cái thứ hai dường như không làm gì hữu ích? (trả lại cùng ngày với date)
Jonathan Lin

4
Tôi hiểu ngay bây giờ: Lần đầu tiên trả về ngày trong múi giờ UTC, với các giá trị ngày theo nghĩa đen của giờ địa phương. Thứ hai trả về ngày trong múi giờ địa phương, nhưng với các giá trị ngày theo nghĩa đen của UTC.
Jonathan Lin

8
Cách tiếp cận này là một cách thực hiện của một mẫu gọi là "dịch chuyển kỷ nguyên", nhằm chuyển kỷ nguyên (dựa trên UTC) sang mô hình được dịch chuyển bởi độ lệch múi giờ hiện tại. Thật không may, mặc dù điều này thường thấy, cách tiếp cận này là thiếu sót. DateĐối tượng của JavaScript sẽ luôn phản ánh kỷ nguyên unix dựa trên UTC và múi giờ địa phương . Triệu chứng rõ ràng khi bạn gọi toStringvào đối tượng ngày kết quả và vẫn thấy múi giờ địa phương, mặc dù bạn dự kiến ​​nó sẽ ở UTC.
Matt Johnson-Pint

2
Nó cũng có thể gây ra lỗi trong các giá trị thời gian, gần các chuyển đổi thời gian tiết kiệm ánh sáng ban ngày của múi giờ địa phương. Nói tóm lại, dịch chuyển kỷ nguyên (thông qua bất kỳ triển khai nào) không hoạt động với Dateđối tượng JavaScript . Một cách khác để thấy điều này ở đây là Date.UTCmong đợi các giá trị dựa trên UTC và bạn đang cung cấp cho nó các giá trị thời gian cục bộ và ngược lại với hàm Datetạo.
Matt Johnson-Pint

70

Đơn giản chỉ cần đặt múi giờ và lấy lại theo

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

Các múi giờ khác như sau

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'
];

8
Điều này nên được đưa lên hàng đầu
Eugene

Ngoại trừ lưu ý rằng điều này không hoạt động trong một số trình duyệt. Ví dụ. IE11.
Paul LeBeau

Lỗi trong Bảng điều khiển IE: Giá trị tùy chọn 'AMERICA / NEW_YORK' cho 'timeZone' nằm ngoài phạm vi hợp lệ. Dự kiến: ['UTC'] @OloghoCyrilPaul
Matee Gojra

1
Rất dễ dàng, rất thanh lịch. Bạn có thể tìm thấy ở đây một danh sách với tất cả các múi giờ stackoverflow.com/questions/38399465/ . Đối với UTC chọn múi giờ London.
EPurpl3

1
Không có giá trị nào trong số đó là "múi giờ", chúng là vị trí đại diện cho cơ sở dữ liệu múi giờ IANA cho các địa điểm có cùng múi giờ địa phương và thay đổi tiết kiệm ánh sáng ban ngày.
RobG

28

Tôi không tin điều này là có thể - không có khả năng đặt múi giờ trên một đối tượng Ngày sau khi nó được tạo.

Và theo một cách nào đó điều này có ý nghĩa - về mặt khái niệm (nếu có lẽ không được thực hiện); mỗi http://en.wikipedia.org/wiki/Unix_timestamp (nhấn mạnh của tôi):

Thời gian Unix, hay thời gian POSIX, là một hệ thống để mô tả thời gian thực, được định nghĩa là số giây trôi qua kể từ nửa đêm Giờ phối hợp quốc tế (UTC) vào thứ Năm, ngày 1 tháng 1 năm 1970.

Khi bạn đã xây dựng nó, nó sẽ thể hiện một điểm nhất định trong thời gian "thực". Múi giờ chỉ có liên quan khi bạn muốn chuyển đổi điểm thời gian trừu tượng đó thành một chuỗi có thể đọc được.

Do đó, điều hợp lý là bạn chỉ có thể thay đổi thời gian thực tế mà Ngày biểu thị trong hàm tạo. Đáng buồn thay, dường như không có cách nào để vượt qua múi giờ rõ ràng - và nhà xây dựng mà bạn đang gọi (có thể nói là chính xác) chuyển các biến thời gian "cục bộ" của bạn sang GMT khi nó lưu trữ chúng theo quy tắc - vì vậy không có cách nào để sử dụngint, int, int tạo Giờ GMT.

Về mặt tích cực, việc sử dụng hàm tạo lấy Chuỗi thay thế là chuyện nhỏ. Bạn thậm chí không phải chuyển đổi tháng số thành Chuỗi (ít nhất là trên Firefox), vì vậy tôi đã hy vọng một triển khai ngây thơ sẽ hoạt động. Tuy nhiên, sau khi dùng thử, nó hoạt động thành công trong Firefox, Chrome và Opera nhưng không thành công trong Konqueror ("Ngày không hợp lệ"), Safari ("Ngày không hợp lệ") và IE ("NaN"). Tôi cho rằng bạn chỉ cần có một mảng tra cứu để chuyển đổi tháng thành một chuỗi, như vậy:

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

function createGMTDate(xiYear, xiMonth, xiDate) {
   return new Date(months[xiMonth] + ' ' + xiDate + ', ' + xiYear + ' 00:00:00 GMT');
}

6
Nếu không có cách nào để "đặt múi giờ trên một đối tượng Ngày sau khi nó được tạo", bạn có ngụ ý rằng có cách nào để đặt múi giờ trên một đối tượng Ngày khi nó được tạo không? Nó không giống như một ngày js là "trình bao bọc mỏng trong một vài giây kể từ Kỷ nguyên" - có vẻ như đó là số giây đó, cộng với múi giờ.
Anthony

1
@Anthony, Nó chỉ có thể sử dụng múi giờ của khách hàng. Javascript có thể làm cục bộ để utc và quay lại nhưng không có quyền truy cập vào cơ sở dữ liệu múi giờ. Chẳng hạn, nó không thể cho bạn biết Thời gian ở Mexico City khi bạn ở San Diego.
Samuel Danielson


16

Nếu bạn muốn xử lý vấn đề hơi khác, nhưng có liên quan, về việc tạo đối tượng Ngày Javascript từ năm, tháng, ngày, ..., bao gồm múi giờ - nghĩa là, nếu bạn muốn phân tích chuỗi thành Ngày - thì bạn rõ ràng phải thực hiện một điệu nhảy phức tạp vô cùng:

// parseISO8601String : string -> Date
// Parse an ISO-8601 date, including possible timezone,
// into a Javascript Date object.
//
// Test strings: parseISO8601String(x).toISOString()
// "2013-01-31T12:34"              -> "2013-01-31T12:34:00.000Z"
// "2013-01-31T12:34:56"           -> "2013-01-31T12:34:56.000Z"
// "2013-01-31T12:34:56.78"        -> "2013-01-31T12:34:56.780Z"
// "2013-01-31T12:34:56.78+0100"   -> "2013-01-31T11:34:56.780Z"
// "2013-01-31T12:34:56.78+0530"   -> "2013-01-31T07:04:56.780Z"
// "2013-01-31T12:34:56.78-0330"   -> "2013-01-31T16:04:56.780Z"
// "2013-01-31T12:34:56-0330"      -> "2013-01-31T16:04:56.000Z"
// "2013-01-31T12:34:56Z"          -> "2013-01-31T12:34:56.000Z"
function parseISO8601String(dateString) {
    var timebits = /^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2})(?::([0-9]*)(\.[0-9]*)?)?(?:([+-])([0-9]{2})([0-9]{2}))?/;
    var m = timebits.exec(dateString);
    var resultDate;
    if (m) {
        var utcdate = Date.UTC(parseInt(m[1]),
                               parseInt(m[2])-1, // months are zero-offset (!)
                               parseInt(m[3]),
                               parseInt(m[4]), parseInt(m[5]), // hh:mm
                               (m[6] && parseInt(m[6]) || 0),  // optional seconds
                               (m[7] && parseFloat(m[7])*1000) || 0); // optional fraction
        // utcdate is milliseconds since the epoch
        if (m[9] && m[10]) {
            var offsetMinutes = parseInt(m[9]) * 60 + parseInt(m[10]);
            utcdate += (m[8] === '+' ? -1 : +1) * offsetMinutes * 60000;
        }
        resultDate = new Date(utcdate);
    } else {
        resultDate = null;
    }
    return resultDate;
}

Nghĩa là, bạn tạo một 'thời gian UTC' bằng cách sử dụng ngày không có múi giờ (để bạn biết địa điểm đó nằm ở đâu, cụ thể là 'địa phương', và nó không được mặc định theo địa phương), sau đó áp dụng bù giờ múi giờ được chỉ định.

Sẽ không hay chút nào nếu ai đó thực sự nghĩ về đối tượng ngày Javascript trong hơn, oooh, năm phút ....


1
cảm ơn vì chức năng tuyệt vời điều duy nhất tôi sẽ thay đổi là thêm hỗ trợ cho dấu hai chấm trong phần bù múi giờ. var timebits = / ^ ([0-9] {4}) - ([0-9] {2}) - ([0-9] {2}) T ([0-9] {2}) :( [0-9] {2}) (? :: ([0-9] *) (\. [0-9] *)?)? (?: ([+ -]) ([0-9] { 2} [:]?) ([0-9] {2}))? /;
robnardo

2
Họ đã nghĩ về nó; thật không may, "họ" là các nhà thiết kế ngôn ngữ Java, vì JS chỉ sao chép lớp Date của Java để triển khai ban đầu.
Xanthir

@Xanthir Oooh, bạn nói đúng và tôi đã quên đối tượng Java Date ban đầu tệ đến mức nào; nhưng ít nhất Java đã từ chối nó và tiếp tục, một thứ Javascript dường như không thể làm được (đó là một ngôn ngữ kỳ quái, Javascript: khá dễ thương và gần như không tệ như lần đầu tiên xuất hiện).
Norman Gray

13
d = new Date();
utc = d.getTime() + (d.getTimezoneOffset() * 60000);
nd = new Date(utc + (3600000*offset));

offset value base on which location time zone you would like to set 
For India offset value +5.5,
New York offset value -4,
London offset value +1

cho tất cả vị trí bù Wiki Danh sách thời gian bù UTC


Làm thế nào điều này giúp cho New York trong thời gian tiết kiệm ánh sáng ban ngày?
frederj

Đối với New York, vui lòng sử dụng giá trị bù -4
Vijay Lathiya

1
Giá trị bù cho New York thay đổi theo thời gian Tiết kiệm ánh sáng ban ngày. Đôi khi nó là -4 và đôi khi là -5 en.wikipedia.org/wiki/Eastern_Time_Zone
frederj

8

getTimeZone Offerset là điểm trừ cho UTC + z.

var d = new Date(xiYear, xiMonth, xiDate);
if(d.getTimezoneOffset() > 0){
    d.setTime( d.getTime() + d.getTimezoneOffset()*60*1000 );
}

1
Một lỗi nhỏ ,! = 0 không> 0. Tôi đã kết thúc việc này
Cristi Băluță

8

Điều này có thể giúp ai đó, đặt UTC vào cuối những gì bạn chuyển đến cho nhà xây dựng mới

Ít nhất là trong chrome bạn có thể nói var date = new Date("2014-01-01 11:00:00 UTC")


1
Trả về "Ngày không hợp lệ" trên Safari
pmrotule

1
Thay thế `UTC` bằng +0000(lưu ý rằng khoảng trống giữa 00 và UTC cần phải được xóa) và điều này sẽ hoạt động trên cả Firefox và Chrome. Mặc dù không chắc chắn cho Safari. (Tham khảo: stackoverflow.com/a/17545854/1273587 )
cytsunny

8

Giải pháp một dòng

new Date(new Date(1422524805305).getTime() - 330*60*1000)

Thay vì 1422524805305, hãy sử dụng dấu thời gian tính bằng mili giây Thay vì 330, hãy sử dụng phần bù múi giờ của bạn trong vài phút. GMT (ví dụ: Ấn Độ +5: 30 là 5 * 60 + 30 = 330 phút)


4
Đây sẽ là mã chạy trên máy khách, nghĩa là múi giờ sẽ khác với những người dùng có vị trí khác nhau của bạn. Giải pháp này sẽ yêu cầu tất cả những ai cần nó sống trong cùng múi giờ (của bạn).
Kevin Beal

@Kevin Beal trong trường hợp đó chỉ cần sử dụng getTimezone Offerset
maximus

6
// My clock 2018-07-25, 00:26:00 (GMT+7)
let date = new Date(); // 2018-07-24:17:26:00 (Look like GMT+0)
const myTimeZone = 7; // my timeZone 
// my timeZone = 7h = 7 * 60 * 60 * 1000 (millisecond);
// 2018-07-24:17:26:00 = x (milliseconds)
// finally, time in milliseconds (GMT+7) = x + myTimezone 
date.setTime( date.getTime() + myTimeZone * 60 * 60 * 1000 );
// date.toISOString() = 2018-07-25, 00:26:00 (GMT+7)

Giải thích mã của bạn và cách giải quyết vấn đề sẽ nâng cao chất lượng câu trả lời của bạn và giúp người dùng học hỏi.
Nic3500

5

Cách dễ nhất mà tôi đã tìm thấy để có được ngày chính xác là sử dụng datejs.

http://www.datejs.com/

Tôi nhận được các ngày của mình thông qua Ajax theo định dạng này dưới dạng chuỗi: '2016-01-12T00: 00: 00'

var yourDateString = '2016-01-12T00:00:00';
var yourDate = new Date(yourDateString);
console.log(yourDate);
if (yourDate.getTimezoneOffset() > 0){
    yourDate = new Date(yourDateString).addMinutes(yourDate.getTimezoneOffset());
}
console.log(yourDate);

Bảng điều khiển sẽ đọc:

Thứ hai, ngày 11 tháng 1 năm 2016 19:00:00 GMT-0500 (Giờ chuẩn miền đông)

Thứ ba ngày 12 tháng 1 năm 2016 00:00:00 GMT-0500 (Giờ chuẩn miền đông)

https://jsfiddle.net/vp1ena7b/3/

'AddMinutes' xuất phát từ datejs, bạn có thể tự mình làm điều này trong js thuần túy, nhưng tôi đã có datejs trong dự án của mình nên tôi đã tìm ra cách sử dụng nó để có được ngày chính xác.

Tôi nghĩ rằng điều này có thể giúp ai đó ...


Đã thử tất cả các phương pháp và đây là cách duy nhất để có được nửa đêm, đó là những gì tôi đã làm sau đó!
SharpC

3

bất kỳ số dặm trong

var d = new Date(xiYear, xiMonth, xiDate).toLocaleString();

Điều này có vẻ là mánh khóe đối với tôi (một múi giờ so với GMT), nhưng vì "miền địa phương" không nhất thiết phải liên quan đến múi giờ, nên tôi sẽ không dựa vào nó.
Wytze

3

Mã này sẽ trả về đối tượng Ngày của bạn được định dạng bằng múi giờ của trình duyệt .

Date.prototype.timezone = function () {
    this.setHours(this.getHours() + (new Date().getTimezoneOffset() / 60));
    return this;
}

Biên tập:

Để tránh làm ô nhiễm API ngày, chức năng trên có thể được chuyển đổi thành chức năng tiện ích. Hàm lấy một đối tượng Date và trả về một đối tượng Date bị đột biến.

function setTimeZone(date) {
    date.setHours(date.getHours() + (new Date().getTimezoneOffset() / 60));
    return date;
}

6
Không mở rộng đối tượng bản địa
Paul Rumkin

1

Giải pháp tốt nhất tôi thấy từ đây đến từ

http://www.codingforums.com/archive/index.php/t-19663.html

Chức năng in thời gian

<script language="javascript" type="text/javascript">
//borrowed from echoecho
//http://www.echoecho.com/ubb/viewthread.php?tid=2362&pid=10482&#pid10482
workDate = new Date()
UTCDate = new Date()
UTCDate.setTime(workDate.getTime()+workDate.getTimezoneOffset()*60000)

function printTime(offset) {
    offset++;
    tempDate = new Date()
    tempDate.setTime(UTCDate.getTime()+3600000*(offset))
    timeValue = ((tempDate.getHours()<10) ? ("0"+tempDate.getHours()) : (""+tempDate.getHours()))
    timeValue += ((tempDate.getMinutes()<10) ? ("0"+tempDate.getMinutes()) : tempDate.getMinutes())
    timeValue += " hrs."
    return timeValue
    }
    var now = new Date()
    var seed = now.getTime() % 0xfffffff
    var same = rand(12)
</script>

Banff, Canada:
<script language="JavaScript">document.write(printTime("-7"))</script>

Ví dụ mã đầy đủ

<html>

<head>
<script language="javascript" type="text/javascript">
//borrowed from echoecho
//http://www.echoecho.com/ubb/viewthread.php?tid=2362&pid=10482&#pid10482
workDate = new Date()
UTCDate = new Date()
UTCDate.setTime(workDate.getTime()+workDate.getTimezoneOffset()*60000)

function printTime(offset) {
offset++;
tempDate = new Date()
tempDate.setTime(UTCDate.getTime()+3600000*(offset))
timeValue = ((tempDate.getHours()<10) ? ("0"+tempDate.getHours()) : (""+tempDate.getHours()))
timeValue += ((tempDate.getMinutes()<10) ? ("0"+tempDate.getMinutes()) : tempDate.getMinutes())
timeValue += " hrs."
return timeValue
}
var now = new Date()
var seed = now.getTime() % 0xfffffff
var same = rand(12)
</script>

</head>

<body>
Banff, Canada:
<script language="JavaScript">document.write(printTime("-7"))</script>
<br>
Michigan:
<script language="JavaScript">document.write(printTime("-5"))</script>
<br>
Greenwich, England(UTC):
<script language="JavaScript">document.write(printTime("-0"))</script>
<br>
Tokyo, Japan:
<script language="JavaScript">document.write(printTime("+9"))</script>
<br>
Berlin, Germany:
<script language="JavaScript">document.write(printTime("+1"))</script>

</body>
</html>

Ví dụ của bạn không bao gồm Thời gian tiết kiệm ánh sáng ban ngày. Thời gian hiện tại: Thứ Sáu 04 tháng 10 năm 2013 11:13:43 GMT-0700 (Giờ ban ngày Thái Bình Dương) UtcTime: Thứ Sáu, 04 Tháng 10 2013 18:13:43 GMT Banff, Canada: 1213 giờ. Michigan: 1413 giờ. Greenwich, Anh (UTC): 1913 giờ. Tokyo, Nhật Bản: 0413 giờ. Berlin, Đức: 2013 giờ.
Jeson Martajaya

0

nếu bạn muốn kiểm tra sự khác biệt về thời gian giữa hai ngày, bạn chỉ cần kiểm tra xem múi giờ thứ hai nhỏ hơn hoặc lớn hơn so với múi giờ mong muốn đầu tiên của bạn và trừ hoặc thêm thời gian.

  const currTimezone = new Date().getTimezoneOffset(); // your timezone
  const newDateTimezone = date.getTimezoneOffset(); // date with unknown timezone

  if (currTimezone !== newDateTimezone) {
    // and below you are checking if difference should be - or +. It depends on if unknown timezone is lesser or greater than yours
    const newTimezone = (currTimezone - newDateTimezone) * (currTimezone > newDateTimezone ? 1 : -1);
    date.setTime(date.getTime() + (newTimezone * 60 * 1000));
  }

0

GMT -03: 00 Ví dụ

new Date(new Date()-3600*1000*3).toISOString();  // 2020-02-27T15:03:26.261Z

Hoặc thậm chí

now  = new Date().getTime()-3600*1000*3; // 1582818380528
data = new Date(now).toISOString();      // 2020-02-27T15:03:26.261Z

-1

Điều này làm việc cho tôi. Không chắc chắn nếu đó là một ý tưởng tốt mặc dù.

var myDate = new Date();
console.log('myDate:', myDate);   // myDate: "2018-04-04T01:09:38.112Z"

var offset = '+5';  // e.g. if the timeZone is -5

var MyDateWithOffset = new Date( myDate.toGMTString() + offset );   

console.log('MyDateWithOffset:', MyDateWithOffset); // myDateWithOffset: "2018-04-03T20:09:38.000Z"


-1

Tôi đã sử dụng gói múi giờ-js.

var timezoneJS  = require('timezone-js');
var tzdata = require('tzdata');

createDate(dateObj) {
    if ( dateObj == null ) {
        return null;
    }
    var nativeTimezoneOffset = new Date().getTimezoneOffset();
    var offset = this.getTimeZoneOffset();

    // use the native Date object if the timezone matches
    if ( offset == -1 * nativeTimezoneOffset ) {
        return dateObj;
    }

    this.loadTimeZones();

    // FIXME: it would be better if timezoneJS.Date was an instanceof of Date
    //        tried jquery $.extend
    //        added hack to Fiterpickr to look for Dater.getTime instead of "d instanceof Date"
    return new timezoneJS.Date(dateObj,this.getTimeZoneName());
},

-11

Đây là giải pháp TỐT NHẤT

Sử dụng:

// TO ALL dates
Date.timezoneOffset(-240) // +4 UTC

// Override offset only for THIS date
new Date().timezoneOffset(-180) // +3 UTC

Mã số:

Date.prototype.timezoneOffset = new Date().getTimezoneOffset();

Date.setTimezoneOffset = function(timezoneOffset) {
  return this.prototype.timezoneOffset = timezoneOffset;
};

Date.getTimezoneOffset = function() {
  return this.prototype.timezoneOffset;
};

Date.prototype.setTimezoneOffset = function(timezoneOffset) {
  return this.timezoneOffset = timezoneOffset;
};

Date.prototype.getTimezoneOffset = function() {
  return this.timezoneOffset;
};

Date.prototype.toString = function() {
  var offsetDate, offsetTime;
  offsetTime = this.timezoneOffset * 60 * 1000;
  offsetDate = new Date(this.getTime() - offsetTime);
  return offsetDate.toUTCString();
};

['Milliseconds', 'Seconds', 'Minutes', 'Hours', 'Date', 'Month', 'FullYear', 'Year', 'Day'].forEach((function(_this) {
  return function(key) {
    Date.prototype["get" + key] = function() {
      var offsetDate, offsetTime;
      offsetTime = this.timezoneOffset * 60 * 1000;
      offsetDate = new Date(this.getTime() - offsetTime);
      return offsetDate["getUTC" + key]();
    };
    return Date.prototype["set" + key] = function(value) {
      var offsetDate, offsetTime, time;
      offsetTime = this.timezoneOffset * 60 * 1000;
      offsetDate = new Date(this.getTime() - offsetTime);
      offsetDate["setUTC" + key](value);
      time = offsetDate.getTime() + offsetTime;
      this.setTime(time);
      return time;
    };
  };
})(this));

Phiên bản cà phê:

Date.prototype.timezoneOffset = new Date().getTimezoneOffset()


Date.setTimezoneOffset = (timezoneOffset)->
    return @prototype.timezoneOffset = timezoneOffset


Date.getTimezoneOffset = ->
    return @prototype.timezoneOffset


Date.prototype.setTimezoneOffset = (timezoneOffset)->
    return @timezoneOffset = timezoneOffset


Date.prototype.getTimezoneOffset = ->
    return @timezoneOffset


Date.prototype.toString = ->
    offsetTime = @timezoneOffset * 60 * 1000
    offsetDate = new Date(@getTime() - offsetTime)
    return offsetDate.toUTCString()


[
    'Milliseconds', 'Seconds', 'Minutes', 'Hours',
    'Date', 'Month', 'FullYear', 'Year', 'Day'
]
.forEach (key)=>
    Date.prototype["get#{key}"] = ->
        offsetTime = @timezoneOffset * 60 * 1000
        offsetDate = new Date(@getTime() - offsetTime)
        return offsetDate["getUTC#{key}"]()

    Date.prototype["set#{key}"] = (value)->
        offsetTime = @timezoneOffset * 60 * 1000
        offsetDate = new Date(@getTime() - offsetTime)
        offsetDate["setUTC#{key}"](value)
        time = offsetDate.getTime() + offsetTime
        @setTime(time)
        return time

2
Ồ, tôi cũng không thích nó, nhưng tôi đoán mọi người thực sự ghét bạn đã ghi đè lên nguyên mẫu của nội dung!
Josh từ Qaribou
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.