แสดงวันที่ / เวลาในรูปแบบตำแหน่งที่ตั้งและเวลาของผู้ใช้


167

ฉันต้องการให้เซิร์ฟเวอร์ให้บริการวันที่เสมอใน UTC ใน HTML และให้ JavaScript บนเว็บไซต์ลูกค้าแปลงเป็นเขตเวลาท้องถิ่นของผู้ใช้

โบนัสถ้าฉันสามารถส่งออกในรูปแบบวันที่สถานที่ของผู้ใช้

คำตอบ:


165

ดูเหมือนว่าวิธีที่จะเข้าใจผิดได้มากที่สุดในการเริ่มต้นด้วยวันที่ UTC คือการสร้างDateวัตถุใหม่และใช้setUTC…วิธีการตั้งค่าเป็นวันที่ / เวลาที่คุณต้องการ

จากนั้นtoLocale…Stringวิธีการต่างๆจะให้ผลลัพธ์ที่แปลเป็นภาษาท้องถิ่น

ตัวอย่าง:

// This would come from the server.
// Also, this whole block could probably be made into an mktime function.
// All very bare here for quick grasping.
d = new Date();
d.setUTCFullYear(2004);
d.setUTCMonth(1);
d.setUTCDate(29);
d.setUTCHours(2);
d.setUTCMinutes(45);
d.setUTCSeconds(26);

console.log(d);                        // -> Sat Feb 28 2004 23:45:26 GMT-0300 (BRT)
console.log(d.toLocaleString());       // -> Sat Feb 28 23:45:26 2004
console.log(d.toLocaleDateString());   // -> 02/28/2004
console.log(d.toLocaleTimeString());   // -> 23:45:26

อ้างอิงบางส่วน:


1
ใน Firefox ให้toLocateDateString()ส่งคืนบางสิ่งที่ดูเหมือน 'วันอาทิตย์ 12 มกราคม 2014' ..
BlueRaja - Danny Pflughoeft

1
อืมใช่มันเป็นปัญหาที่ร้ายแรงทีเดียว การใช้วิธีการเหล่านี้จะไม่ทำงานหากคุณต้องการให้วันที่ดูเหมือนกันในเบราว์เซอร์ ทางเลือกใด ๆ ที่รู้จักกัน?
Josh Mc

6
รุ่นบรรทัดเดียวของการเริ่มต้นด้านบน:var d = new Date(Date.UTC(2004,1,29,2,45,26));
m1kael

4
มันอาจจะคุ้มค่าเมื่อพิจารณาว่า Chrome (ณ วันที่ v35) ไม่ได้คำนึงถึงสถานที่ของผู้ใช้ในtoLocaleString()ฟังก์ชั่น
benno

8
ฉันขอโทษ แต่วิธีนี้ใช้ไม่ได้ผล (ฉันอยู่ในออสเตรเลีย) เมื่อฉันเรียกใช้รหัสข้างต้นวันที่จะแสดงในรูปแบบสหรัฐอเมริกา นอกจากนี้MDNบอกว่า 'โลแคลที่ใช้และรูปแบบของสตริงที่ส่งคืนนั้นขึ้นอยู่กับการใช้งานทั้งหมด'
tgrrr

65

สำหรับโครงการใหม่เพียงใช้moment.js

คำถามนี้ค่อนข้างเก่าสักครู่ดังนั้นจึงไม่มีอยู่ในขณะนั้น แต่สำหรับโครงการใหม่มันทำให้งานแบบนี้ง่ายขึ้นมาก

วิธีที่ดีที่สุดคือการแยกสตริงวันที่ของคุณจาก UTC ดังนี้ (สร้างสตริงที่เข้ากันได้กับISO-8601บนเซิร์ฟเวอร์เพื่อให้ได้ผลลัพธ์ที่สอดคล้องกันในทุกเบราว์เซอร์):

var m = moment("2013-02-08T09:30:26Z");

ตอนนี้ใช้mในแอปพลิเคชันของคุณสักครู่ค่าเริ่มต้นของโซนเวลาท้องถิ่นสำหรับการดำเนินการแสดงผล มีหลายวิธีในการจัดรูปแบบค่าวันที่และเวลาหรือแยกส่วนของมัน

คุณสามารถจัดรูปแบบวัตถุช่วงเวลาในสถานที่ของผู้ใช้เช่นนี้:

m.format('LLL') // Returns "February 8 2013 8:30 AM" on en-us

ที่จะเปลี่ยนวัตถุ moment.js เป็นเขตเวลาที่แตกต่างกัน (เช่นค่าหนึ่งในท้องถิ่นหรือ UTC), คุณจะต้องขยายเขต moment.js หน้านั้นยังมีตัวอย่างบางส่วนมันใช้งานง่ายมาก


คุณจะรวมทั้งหมดนี้ได้อย่างไร m.utcOffset (offset) .format ('LLL') ดูเหมือนจะไม่ทำงาน
บาร์ต

ควรLuxonหรือDay.jsเป็นห้องสมุดปัญหาตอนนี้หรือไม่
โฮเมอร์

1
ฉันแนะนำให้เพิ่มFor old projects, just use jQuery
Xenos

ใช้งานไม่ได้กับโครเมียม - ยังคงแสดงเวลา am / pm แม้ว่าเวลาจะถูกตั้งค่าเป็น 24 ชั่วโมงในการตั้งค่าตำแหน่งที่ตั้งของคอมพิวเตอร์
vir us

20

คุณสามารถใช้new Date().getTimezoneOffset()/60สำหรับเขตเวลา นอกจากนี้ยังมีtoLocaleString()วิธีการแสดงวันที่โดยใช้ภาษาของผู้ใช้

นี่คือรายการทั้งหมด: การทำงานกับวันที่


toLocaleStringไม่น่าเชื่อถืออย่างยิ่งสำหรับการนำเสนอวันที่ในรูปแบบที่ผู้ใช้อาจคาดหวัง แม้ว่า ISO 402 จะรองรับ แต่ก็ยังไม่น่าเชื่อถือมากและใช้รูปแบบกับภาษาไม่ใช่โลแคล
RobG

@RobG แก้ปัญหาแทนtoLocaleStringอะไร
924

@ user924— คุณสามารถใช้ห้องสมุดมีให้เลือกมากมาย ปัญหาเกี่ยวกับtoLocaleStringคือการใช้งานที่แตกต่างกันให้ผลลัพธ์ที่แตกต่างพร้อมการสนับสนุนระดับต่าง ๆ สำหรับภาษาและภูมิภาคต่างๆ เช่นภาษาเริ่มต้นของระบบของฉันไม่ใช่ en-US แต่รูปแบบเริ่มต้นสำหรับtoLocaleStringสำหรับเบราว์เซอร์บางตัวเป็นรูปแบบสหรัฐฯส่วนอื่น ๆ ก็เคารพภาษาระบบของฉัน เหมือนกับชื่อเขตเวลาเท่านั้นที่แย่กว่านั้นเพราะพวกเขาไม่ได้มาตรฐาน :-(
RobG

7

เมื่อคุณสร้างวัตถุวันที่ของคุณแล้วนี่เป็นตัวอย่างข้อมูลสำหรับการแปลง:

ฟังก์ชั่นใช้วัตถุวันที่จัดรูปแบบ UTC และสตริงรูปแบบ
คุณจะต้องมีDate.strftimeต้นแบบ

function UTCToLocalTimeString(d, format) {
    if (timeOffsetInHours == null) {
        timeOffsetInHours = (new Date().getTimezoneOffset()/60) * (-1);
    }
    d.setHours(d.getHours() + timeOffsetInHours);

    return d.strftime(format);
}

6
คุณมาจากที่ไหน
Anuj Pandey

การตั้งค่าชั่วโมงมีผลกับส่วนของวัน / วันที่ / ปีของวัตถุวันที่หรือไม่? ดูเหมือนจะไม่
ChristoKiwi

1
@ ChristoKiwi - ค่าที่ส่งไปยังsetHoursคาดว่าจะเป็นจำนวนเต็มgetTimezoneOffset()/60อาจส่งกลับเศษส่วน (เช่นอินเดียชดเชย +05: 30 จะส่งคืน 5.5) ทศนิยมถูกปัดเศษ มิฉะนั้นการตั้งค่าเวลาจะอัปเดตค่าอื่น ๆ (ตั้งค่าชั่วโมงเป็น 48 และดูว่าเกิดอะไรขึ้น)
RobG

7

ใน JS ไม่มีวิธีที่ง่ายและข้ามแพลตฟอร์มในการจัดรูปแบบวันที่เวลาท้องถิ่นนอกเหนือจากการแปลงสถานที่ให้บริการแต่ละรายการดังกล่าวข้างต้น

นี่คือแฮ็คด่วนที่ฉันใช้รับ YYYY-MM-DD ในพื้นที่ โปรดทราบว่านี่เป็นแฮ็คเนื่องจากวันสุดท้ายจะไม่มีเขตเวลาที่ถูกต้องอีกต่อไป (ดังนั้นคุณต้องข้ามเขตเวลา) หากฉันต้องการสิ่งอื่นเพิ่มเติมฉันใช้ moment.js

var d = new Date();    
d = new Date(d.getTime() - d.getTimezoneOffset() * 60000)
var yyyymmdd = t.toISOString().slice(0,0); 
// 2017-05-09T08:24:26.581Z (but this is not UTC)

d.getTimezoneOffset () คืนค่าเขตเวลาชดเชยในหน่วยนาทีและ d.getTime () เป็น ms ดังนั้น x 60,000


1
@VG ฉันได้เพิ่มข้อมูลเพิ่มเติมเกี่ยวกับ 60k มาจากไหน หวังว่าความช่วยเหลือนี้
Jeremy Chone

5

นี่คือสิ่งที่ฉันใช้ในโครงการที่ผ่านมา:

var myDate = new Date();
var tzo = (myDate.getTimezoneOffset()/60)*(-1);
//get server date value here, the parseInvariant is from MS Ajax, you would need to do something similar on your own
myDate = new Date.parseInvariant('<%=DataCurrentDate%>', 'yyyyMMdd hh:mm:ss');
myDate.setHours(myDate.getHours() + tzo);
//here you would have to get a handle to your span / div to set.  again, I'm using MS Ajax's $get
var dateSpn = $get('dataDate');
dateSpn.innerHTML = myDate.localeFormat('F');

4
นี่คือสิ่งที่เฉพาะ ASP.NET
ZiggyTheHamster

การปรับเวลาในเขตเวลานั้นไม่จำเป็นต้องเพิ่มทวีคูณของชั่วโมงดังนั้นgetTimezoneOffset()/60มักจะส่งกลับค่าทศนิยม นี่เป็นเรื่องจริงโดยเฉพาะอย่างยิ่งสำหรับวันที่ก่อนปี 1900 ที่หลายแห่งมีการชดเชยในนาทีและวินาที นอกจากนี้จำเป็นต้องใช้วันที่จาวาสคริปต์เพื่อสนับสนุนการหักล้างประวัติ เช่นในปี 1890 การชดเชยในมอสโกคือ +2: 30: 17 ดูเบราว์เซอร์, โซนเวลา Chrome 67 ข้อผิดพลาด
RobG

3

.getTimezoneOffset()วิธีการรายงานเขตเวลาชดเชยในนาทีนับ "ตะวันตก" จากเขตเวลา GMT / UTC ส่งผลให้ค่าชดเชยที่เป็นลบกับสิ่งที่หนึ่งจะคุ้นเคยกันทั่วไป (ตัวอย่าง, เวลานิวยอร์กจะถูกรายงานให้เป็น +240 นาทีหรือ +4 ชั่วโมง)

ในการรับการชดเชยเวลาปกติในหน่วยชั่วโมงคุณต้องใช้:

var timeOffsetInHours = -(new Date()).getTimezoneOffset()/60

รายละเอียดที่สำคัญ:
โปรดทราบว่าการปรับเวลาตามฤดูกาลเป็นปัจจัยสำคัญในผลลัพธ์ - ดังนั้นวิธีการนี้ให้เวลาชดเชยกับคุณจริงๆ- ไม่ใช่การชดเชยเวลาทางภูมิศาสตร์ตามโซนเวลาจริง


3

ด้วยวันที่จากรหัส PHP ฉันใช้สิ่งนี้ ..

function getLocalDate(php_date) {
  var dt = new Date(php_date);
  var minutes = dt.getTimezoneOffset();
  dt = new Date(dt.getTime() + minutes*60000);
  return dt;
}

เราเรียกมันได้เช่นนี้

var localdateObj = getLocalDate('2015-09-25T02:57:46');

คำถามเกี่ยวกับ JavaScript ไม่ใช่ PHP
pipedreambomb

5
คำตอบอยู่ในรูปแบบจาวาสคริปต์เท่านั้นมีการกล่าวถึงในวันที่เซิร์ฟเวอร์เป็น UTC ดังนั้นเซิร์ฟเวอร์อาจเป็นภาษาใดก็ได้ ดังนั้นฉันจึงตอบ PHP เท่านั้น
hriziya

3

ฉันผสมคำตอบจนถึงตอนนี้และเพิ่มเข้าไปเพราะฉันต้องอ่านคำตอบทั้งหมดและตรวจสอบเพิ่มเติมในขณะนี้เพื่อแสดงสตริงวันที่จาก db ในรูปแบบเขตเวลาท้องถิ่นของผู้ใช้

สตริง datetime มาจาก python / django db ในรูปแบบ: 2016-12-05T15: 12: 24.215Z

การตรวจสอบความน่าเชื่อถือของภาษาเบราว์เซอร์ใน JavaScript ดูเหมือนจะไม่ทำงานในทุกเบราว์เซอร์ (ดูJavaScript สำหรับตรวจจับการตั้งค่าภาษาเบราว์เซอร์ ) ดังนั้นฉันจึงได้รับภาษาเบราว์เซอร์จากเซิร์ฟเวอร์

Python / Django: ส่งภาษาเบราว์เซอร์คำขอเป็นพารามิเตอร์บริบท:

language = request.META.get('HTTP_ACCEPT_LANGUAGE')
return render(request, 'cssexy/index.html', { "language": language })

HTML: เขียนในอินพุตที่ซ่อนอยู่:

<input type="hidden" id="browserlanguage" value={{ language }}/>

JavaScript: รับค่าอินพุตที่ซ่อนอยู่เช่น en-GB, en-US; q = 0.8, en; q = 0.6 / จากนั้นใช้ภาษาแรกในรายการเท่านั้นผ่านการแทนที่และการแสดงออกปกติ

const browserlanguage = document.getElementById("browserlanguage").value;
var defaultlang = browserlanguage.replace(/(\w{2}\-\w{2}),.*/, "$1");

JavaScript: แปลงเป็น datetime และจัดรูปแบบ:

var options = { hour: "2-digit", minute: "2-digit" };
var dt = (new Date(str)).toLocaleDateString(defaultlang, options);

ดู: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString

ผลลัพธ์คือ (ภาษาเบราว์เซอร์คือ en-gb): 05/12/2016, 14:58


3

// new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]])
var serverDate = new Date(2018, 5, 30, 19, 13, 15); // just any date that comes from server
var serverDateStr = serverDate.toLocaleString("en-US", {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric'
})
var userDate = new Date(serverDateStr + " UTC");
var locale = window.navigator.userLanguage || window.navigator.language;

var clientDateStr = userDate.toLocaleString(locale, {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric'
});

var clientDateTimeStr = userDate.toLocaleString(locale, {
  year: 'numeric',
  month: 'numeric',
  day: 'numeric',
  hour: 'numeric',
  minute: 'numeric',
  second: 'numeric'
});

console.log("Server UTC date: " + serverDateStr);
console.log("User's local date: " + clientDateStr);
console.log("User's local date&time: " + clientDateTimeStr);


สำหรับการอ้างอิง: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ … (ฉันต้องการoptionsส่วนสำหรับกรณีของฉัน)
Xenos

2

ทางออกที่ดีที่สุดที่ฉันเจอคือการสร้าง [time display = "llll" datetime = "UTC TIME" /] แท็กและใช้ javascript (jquery) เพื่อแยกวิเคราะห์และแสดงสัมพันธ์กับเวลาของผู้ใช้

http://momentjs.com/ Moment.js

จะแสดงเวลาอย่างสวยงาม


2

คุณสามารถใช้สิ่งต่อไปนี้ซึ่งรายงานเขตเวลาชดเชยจาก GMT ในไม่กี่นาที:

new Date().getTimezoneOffset();

หมายเหตุ: - ฟังก์ชั่นนี้คืนค่าจำนวนลบ


1

getTimeZoneOffset () และ toLocaleString เป็นสิ่งที่ดีสำหรับการทำงานวันขั้นพื้นฐาน แต่ถ้าคุณต้องการการสนับสนุนเขตเวลาจริงดูที่TimeZone.js MDE ของ

มีตัวเลือกเพิ่มเติมสองสามตัวที่กล่าวถึงในคำตอบสำหรับคำถามนี้


1

ในการแปลงวันที่เป็นวันที่ท้องถิ่นให้ใช้วิธี toLocaleDateString ()

var date = (new Date(str)).toLocaleDateString(defaultlang, options);

ในการแปลงเวลาเป็นเวลาท้องถิ่นให้ใช้เมธอด toLocaleTimeString ()

var time = (new Date(str)).toLocaleTimeString(defaultlang, options);

-12

ไม่ทราบวิธีการทำสถานที่ แต่จาวาสคริปต์เป็นเทคโนโลยีฝั่งไคลเอ็นต์

usersLocalTime = new Date();

จะมีเวลาและวันที่ของลูกค้าในนั้น (ตามที่รายงานโดยเบราว์เซอร์ของพวกเขาและโดยการขยายคอมพิวเตอร์ที่พวกเขานั่งอยู่) มันควรจะเป็นเรื่องเล็กน้อยที่จะรวมเวลาของเซิร์ฟเวอร์ในการตอบสนองและทำคณิตศาสตร์ง่าย ๆ เพื่อชดเชยการคาดเดา

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.