มีวิธีที่เชื่อถือได้ในการรับเขตเวลาจากเบราว์เซอร์ไคลเอ็นต์หรือไม่ ฉันเห็นลิงค์ต่อไปนี้ แต่ฉันต้องการโซลูชันที่มีประสิทธิภาพมากขึ้น
มีวิธีที่เชื่อถือได้ในการรับเขตเวลาจากเบราว์เซอร์ไคลเอ็นต์หรือไม่ ฉันเห็นลิงค์ต่อไปนี้ แต่ฉันต้องการโซลูชันที่มีประสิทธิภาพมากขึ้น
คำตอบ:
ดูที่เก็บของเจดีย์นี้จะเป็นประโยชน์
ดาวน์โหลด jstz.min.js และเพิ่มฟังก์ชั่นในหน้า html ของคุณ
<script language="javascript">
function getTimezoneName() {
timezone = jstz.determine()
return timezone.name();
}
</script>
และเรียกใช้ฟังก์ชันนี้จากแท็กที่แสดงของคุณ
Intl.DateTimeFormat().resolvedOptions().timeZone
(ไม่ใช่ IE11) ตามที่ Wallace แนะนำ
ครึ่งทศวรรษต่อมาเรามีวิธีในตัวสำหรับมัน! สำหรับเบราว์เซอร์ที่ทันสมัยฉันจะใช้:
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tz);
ผลตอบแทนนี้สตริงเขต IANA แต่ไม่ชดเชย เรียนรู้เพิ่มเติมที่อ้างอิง MDN
ตารางความเข้ากันได้ - ณ เดือนมีนาคม 2562 ทำงานได้ 90% ของเบราว์เซอร์ที่ใช้งานทั่วโลก ไม่สามารถทำงานได้บน Internet Explorer
Intl.DateTimeFormat().resolvedOptions().timeZone
->undefined
Intl.DateTimeFormat().resolvedOptions().timeZone
จะคืนค่าที่คาดหวังเริ่มต้นจาก Firefox 52: kangax.github.io/compat-table/esintl/…
บ่อยครั้งที่ผู้คนกำลังมองหา "เขตเวลา" สิ่งที่พอเพียงคือ "UTC offset" เช่นเซิร์ฟเวอร์ของตนอยู่ใน UTC + 5 และพวกเขาต้องการที่จะรู้ว่าลูกค้าของพวกเขากำลังทำงานใน UTC-8
ในจาวาสคริปต์แบบธรรมดาธรรมดา(new Date()).getTimezoneOffset()/60
จะคืนค่าจำนวนชั่วโมงปัจจุบันชดเชยจาก UTC
เป็นเรื่องที่ควรสังเกตว่า "gotcha" ที่เป็นไปได้ในสัญลักษณ์ของgetTimezoneOffset()
ค่าส่งคืน(จากเอกสาร MDN) :
ออฟเซ็ตเขตเวลาคือความแตกต่างเป็นนาทีระหว่าง UTC กับเวลาท้องถิ่น โปรดทราบว่านี่หมายความว่าการชดเชยเป็นค่าบวกหากเขตเวลาท้องถิ่นอยู่หลัง UTC และลบหากอยู่ข้างหน้า ตัวอย่างเช่นสำหรับเขตเวลา UTC + 10: 00 (เวลามาตรฐานของออสเตรเลียตะวันออก, เวลาวลาดิวอสต็อก, เวลามาตรฐาน Chamorro), -600 จะถูกส่งกลับ
แต่ผมแนะนำให้คุณใช้day.jsเวลา / วันที่ที่เกี่ยวข้องกับรหัส Javascript ในกรณีนี้คุณจะได้รับออฟเซ็ต UTC 8601 รูปแบบ ISO ด้วยการรัน:
> dayjs().format("Z")
"-08:00"
เป็นไปได้ว่าลูกค้าอาจปลอมแปลงข้อมูลนี้ได้อย่างง่ายดาย
(หมายเหตุ: คำตอบนี้ แต่เดิมแนะนำhttps://momentjs.com/แต่ dayjs เป็นทางเลือกที่ทันสมัยและเล็กลง)
สำหรับตอนนี้ทางออกที่ดีที่สุดอาจจะ jstz เป็นข้อเสนอแนะในคำตอบของ mbayloon
เพื่อความสมบูรณ์ก็ควรจะกล่าวว่ามีความเป็นมาตรฐานที่เป็นของทาง: สนามบินนานาชาติ คุณสามารถเห็นสิ่งนี้ใน Chrome แล้ว:
> Intl.DateTimeFormat().resolvedOptions().timeZone
"America/Los_Angeles"
(สิ่งนี้ไม่ได้เป็นไปตามมาตรฐานซึ่งเป็นอีกเหตุผลหนึ่งที่ควรยึดติดกับห้องสมุด)
Intl
ควรจะกลับมาundefined
สำหรับคุณสมบัติถ้าคุณไม่ได้ด้วยตนเองระบุเขตเวลาในการก่อสร้างtimeZone
DateTimeFormat
Chrome เบี่ยงเบนจากมาตรฐานโดยส่งคืนเขตเวลาของระบบแทน นั่นคือสิ่งที่คำตอบของโยฮันเนสหาประโยชน์ แต่ก็เป็นสาเหตุที่เขาพูดว่า "ไม่ปฏิบัติตามมาตรฐาน"
คุณสามารถใช้เขตเวลาเพื่อเดาเขตเวลา:
> moment.tz.guess()
"America/Asuncion"
นี่คือjsfiddle
มันแสดงตัวย่อของเขตเวลาของผู้ใช้ปัจจุบัน
นี่คือตัวอย่างโค้ด
var tz = jstz.determine();
console.log(tz.name());
console.log(moment.tz.zone(tz.name()).abbr(new Date().getTime()));
May 22 2015 03:45 PM CDT
ฉันใช้ console.log(moment(now).format('MMM DD YYYY hh:mm A') + ' ' + moment.tz.zone(tz.name()).abbr(now.getTime()));
ฉันใช้วิธีการที่คล้ายกับวิธีที่Josh Fraser ใช้ซึ่งกำหนดเวลาเบราว์เซอร์จาก UTC และระบุว่ารู้จัก DST หรือไม่ (แต่ค่อนข้างง่ายจากรหัสของเขา):
var ClientTZ = {
UTCoffset: 0, // Browser time offset from UTC in minutes
UTCoffsetT: '+0000S', // Browser time offset from UTC in '±hhmmD' form
hasDST: false, // Browser time observes DST
// Determine browser's timezone and DST
getBrowserTZ: function () {
var self = ClientTZ;
// Determine UTC time offset
var now = new Date();
var date1 = new Date(now.getFullYear(), 1-1, 1, 0, 0, 0, 0); // Jan
var diff1 = -date1.getTimezoneOffset();
self.UTCoffset = diff1;
// Determine DST use
var date2 = new Date(now.getFullYear(), 6-1, 1, 0, 0, 0, 0); // Jun
var diff2 = -date2.getTimezoneOffset();
if (diff1 != diff2) {
self.hasDST = true;
if (diff1 - diff2 >= 0)
self.UTCoffset = diff2; // East of GMT
}
// Convert UTC offset to ±hhmmD form
diff2 = (diff1 < 0 ? -diff1 : diff1) / 60;
var hr = Math.floor(diff2);
var min = diff2 - hr;
diff2 = hr * 100 + min * 60;
self.UTCoffsetT = (diff1 < 0 ? '-' : '+') + (hr < 10 ? '0' : '') + diff2.toString() + (self.hasDST ? 'D' : 'S');
return self.UTCoffset;
}
};
// Onload
ClientTZ.getBrowserTZ();
เมื่อทำการโหลดClientTZ.getBrowserTZ()
ฟังก์ชั่นจะถูกดำเนินการซึ่งตั้งค่า:
ClientTZ.UTCoffset
ถึงเวลาเบราว์เซอร์ที่ชดเชยจาก UTC ในหน่วยนาที (เช่น CST คือ −360 นาทีซึ่งคือ .06.0 ชั่วโมงจาก UTC)ClientTZ.UTCoffsetT
เพื่อชดเชยในรูปแบบ'±hhmmD'
(เช่น, '-0600D'
), ที่ต่อท้ายเป็นD
สำหรับ DST และS
สำหรับมาตรฐาน (ไม่ใช่ -DST);ClientTZ.hasDST
(เป็นจริงหรือเท็จ)ClientTZ.UTCoffset
มีให้ในนาทีแทนชั่วโมงเพราะเขตบางรายที่มีการชดเชยรายชั่วโมงเศษ (เช่น 0415)
ที่อยู่เบื้องหลังความตั้งใจClientTZ.UTCoffsetT
ที่จะใช้เป็นคีย์ลงในตารางของเขต (ไม่ได้ให้ที่นี่) เช่นสำหรับหล่นลง<select>
รายการ
7-1
สำหรับกรกฎาคมแทนมิถุนายน ฉันไม่แน่ใจว่ามันสร้างความแตกต่างอย่างแท้จริงหรือไม่เนื่องจากฉันสงสัยว่ามีแผนการ DST ระดับภูมิภาคซึ่งไม่รวมมิถุนายน
ไม่ไม่มีวิธีที่เชื่อถือได้เพียงอย่างเดียวและจะไม่มีทาง คุณคิดว่าคุณเชื่อถือลูกค้าได้หรือไม่?