ฉันมีข้อสงสัยว่าคำตอบไม่ได้ให้ผลลัพธ์ที่ถูกต้อง ในคำถามผู้ถามต้องการแปลงการประทับเวลาจากเซิร์ฟเวอร์เป็นเวลาปัจจุบันใน Hellsinki โดยไม่คำนึงถึงเขตเวลาปัจจุบันของผู้ใช้
เป็นความจริงที่ว่าเขตเวลาของผู้ใช้อาจเป็นสิ่งที่เราไม่สามารถเชื่อถือได้
ถ้าเช่น. การประทับเวลาคือ 1270544790922 และเรามีฟังก์ชัน:
var _date = new Date();
_date.setTime(1270544790922);
var _helsenkiOffset = 2*60*60;//maybe 3
var _userOffset = _date.getTimezoneOffset()*60*60;
var _helsenkiTime = new Date(_date.getTime()+_helsenkiOffset+_userOffset);
เมื่อชาวนิวยอร์กเข้าชมหน้าการแจ้งเตือน (_helsenkiTime) จะพิมพ์:
Tue Apr 06 2010 05:21:02 GMT-0400 (EDT)
และเมื่อชาวฟินแลนด์เข้าชมหน้าการแจ้งเตือน (_helsenkiTime) จะพิมพ์:
Tue Apr 06 2010 11:55:50 GMT+0300 (EEST)
ดังนั้นฟังก์ชันจะถูกต้องก็ต่อเมื่อผู้เยี่ยมชมเพจมีเขตเวลาเป้าหมาย (ยุโรป / เฮลซิงกิ) ในคอมพิวเตอร์ของเขา แต่ล้มเหลวในเกือบทุกส่วนของโลก และเนื่องจากการประทับเวลาของเซิร์ฟเวอร์มักจะเป็นการประทับเวลา UNIX ซึ่งตามคำจำกัดความใน UTC จำนวนวินาทีนับตั้งแต่ Unix Epoch (1 มกราคม 1970 00:00:00 GMT) เราจึงไม่สามารถระบุ DST หรือไม่ใช่ DST จากการประทับเวลาได้
ดังนั้นวิธีแก้ปัญหาคือการยกเลิกเขตเวลาปัจจุบันของผู้ใช้และใช้วิธีคำนวณค่าชดเชย UTC ว่าวันที่อยู่ใน DST หรือไม่ Javascript ไม่มีวิธีดั้งเดิมในการกำหนดประวัติการเปลี่ยน DST ของเขตเวลาอื่นที่ไม่ใช่เขตเวลาปัจจุบันของผู้ใช้ เราสามารถบรรลุสิ่งนี้ได้อย่างง่ายดายที่สุดโดยใช้สคริปต์ฝั่งเซิร์ฟเวอร์เพราะเราสามารถเข้าถึงฐานข้อมูลเขตเวลาของเซิร์ฟเวอร์ได้อย่างง่ายดายพร้อมด้วยประวัติการเปลี่ยนแปลงทั้งหมดของเขตเวลาทั้งหมด
แต่ถ้าคุณไม่สามารถเข้าถึงฐานข้อมูลเขตเวลาของเซิร์ฟเวอร์ (หรือเซิร์ฟเวอร์อื่น ๆ ) ได้และการประทับเวลาอยู่ใน UTC คุณสามารถรับฟังก์ชันที่คล้ายกันได้โดยการเข้ารหัสกฎ DST ใน Javascript
เพื่อให้ครอบคลุมวันที่ในปี 1998-2099 ในยุโรป / เฮลซิงกิคุณสามารถใช้ฟังก์ชันต่อไปนี้ ( jsfiddled ):
function timestampToHellsinki(server_timestamp) {
function pad(num) {
num = num.toString();
if (num.length == 1) return "0" + num;
return num;
}
var _date = new Date();
_date.setTime(server_timestamp);
var _year = _date.getUTCFullYear();
// Return false, if DST rules have been different than nowadays:
if (_year<=1998 && _year>2099) return false;
// Calculate DST start day, it is the last sunday of March
var start_day = (31 - ((((5 * _year) / 4) + 4) % 7));
var SUMMER_start = new Date(Date.UTC(_year, 2, start_day, 1, 0, 0));
// Calculate DST end day, it is the last sunday of October
var end_day = (31 - ((((5 * _year) / 4) + 1) % 7))
var SUMMER_end = new Date(Date.UTC(_year, 9, end_day, 1, 0, 0));
// Check if the time is between SUMMER_start and SUMMER_end
// If the time is in summer, the offset is 2 hours
// else offset is 3 hours
var hellsinkiOffset = 2 * 60 * 60 * 1000;
if (_date > SUMMER_start && _date < SUMMER_end) hellsinkiOffset =
3 * 60 * 60 * 1000;
// Add server timestamp to midnight January 1, 1970
// Add Hellsinki offset to that
_date.setTime(server_timestamp + hellsinkiOffset);
var hellsinkiTime = pad(_date.getUTCDate()) + "." +
pad(_date.getUTCMonth()) + "." + _date.getUTCFullYear() +
" " + pad(_date.getUTCHours()) + ":" +
pad(_date.getUTCMinutes()) + ":" + pad(_date.getUTCSeconds());
return hellsinkiTime;
}
ตัวอย่างการใช้งาน:
var server_timestamp = 1270544790922;
document.getElementById("time").innerHTML = "The timestamp " +
server_timestamp + " is in Hellsinki " +
timestampToHellsinki(server_timestamp);
server_timestamp = 1349841923 * 1000;
document.getElementById("time").innerHTML += "<br><br>The timestamp " +
server_timestamp + " is in Hellsinki " + timestampToHellsinki(server_timestamp);
var now = new Date();
server_timestamp = now.getTime();
document.getElementById("time").innerHTML += "<br><br>The timestamp is now " +
server_timestamp + " and the current local time in Hellsinki is " +
timestampToHellsinki(server_timestamp);
และสิ่งนี้จะพิมพ์สิ่งต่อไปนี้โดยไม่คำนึงถึงเขตเวลาของผู้ใช้:
The timestamp 1270544790922 is in Hellsinki 06.03.2010 12:06:30
The timestamp 1349841923000 is in Hellsinki 10.09.2012 07:05:23
The timestamp is now 1349853751034 and the current local time in Hellsinki is 10.09.2012 10:22:31
แน่นอนว่าหากคุณสามารถส่งคืนการประทับเวลาในรูปแบบที่มีการเพิ่มออฟเซ็ต (DST หรือไม่ใช่ DST หนึ่ง) ลงในการประทับเวลาบนเซิร์ฟเวอร์แล้วคุณไม่จำเป็นต้องคำนวณไคลเอนต์ไซด์และคุณสามารถลดความซับซ้อนของฟังก์ชันได้มาก แต่อย่าลืมอย่าใช้ timezoneOffset () เพราะคุณต้องจัดการกับเขตเวลาของผู้ใช้และนี่ไม่ใช่พฤติกรรมที่ต้องการ