Hiển thị ngày / giờ ở định dạng ngôn ngữ của người dùng và thời gian bù


167

Tôi muốn máy chủ luôn phục vụ ngày trong UTC trong HTML và có JavaScript trên trang web của khách hàng chuyển đổi nó thành múi giờ địa phương của người dùng.

Tiền thưởng nếu tôi có thể xuất ra ở định dạng ngày địa phương của người dùng.

Câu trả lời:


165

Có vẻ cách dễ nhất để bắt đầu với ngày UTC là tạo một Dateđối tượng mới và sử dụng các setUTC…phương thức để đặt nó vào ngày / giờ bạn muốn.

Sau đó, các toLocale…Stringphương pháp khác nhau sẽ cung cấp đầu ra cục bộ.

Thí dụ:

// 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

Một số tài liệu tham khảo:


1
Trong Firefox, toLocateDateString()trả về một cái gì đó trông giống như 'Chủ nhật, ngày 12 tháng 1 năm 2014' ..
BlueRaja - Danny Pflughoeft

1
Hmm vâng, nó là một vấn đề khá nghiêm trọng. Sử dụng các phương pháp này sẽ không hoạt động nếu bạn muốn ngày giống nhau trên các trình duyệt. Bất kỳ lựa chọn thay thế được biết đến?
Josh Mc

6
Phiên bản một dòng của khởi tạo ở trên:var d = new Date(Date.UTC(2004,1,29,2,45,26));
m1kael

4
Có thể đáng để xem xét rằng Chrome (kể từ v35) không tính đến ngôn ngữ của người dùng trong các toLocaleString()chức năng.
benno

8
Tôi xin lỗi nhưng phương pháp này không hoạt động (Tôi đang ở Úc), khi tôi chạy đoạn mã trên, ngày được hiển thị ở định dạng Hoa Kỳ. Hơn nữa, MDN nói rằng "miền địa phương được sử dụng và dạng chuỗi được trả về hoàn toàn phụ thuộc vào việc thực hiện".
tgrrr

65

Đối với các dự án mới, chỉ cần sử dụng khoảnh khắc

Câu hỏi này khá cũ, vì vậy khoảnh khắc đó không tồn tại vào thời điểm đó, nhưng đối với các dự án mới, nó đơn giản hóa rất nhiều nhiệm vụ như thế này rất nhiều.

Tốt nhất là phân tích chuỗi ngày của bạn từ UTC như sau (tạo chuỗi tương thích ISO-8601 trên máy chủ để có kết quả nhất quán trên tất cả các trình duyệt):

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

Bây giờ chỉ cần sử dụng mtrong ứng dụng của bạn, khoảnh khắc mặc định theo múi giờ cục bộ cho các hoạt động hiển thị. Có nhiều cách để định dạng các giá trị ngày và thời gian hoặc trích xuất các phần của nó.

Bạn thậm chí có thể định dạng một đối tượng khoảnh khắc trong ngôn ngữ người dùng như thế này:

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

Để chuyển đổi một đối tượng Moment.js thành một múi giờ khác (tức là không phải cục bộ cũng không phải UTC), bạn sẽ cần tiện ích mở rộng múi giờ của Moment.js . Trang đó cũng có một số ví dụ, nó khá đơn giản để sử dụng.


Làm thế nào để bạn kết hợp tất cả điều này? m.utc Offerset (offset) .format ('LLL') dường như không hoạt động.
bart

Có nên Luxon hoặc Day.js là thư viện đề nghị bây giờ?
Homer

1
Tôi đề nghị thêmFor old projects, just use jQuery
Xenos

Không hoạt động trên chrome - vẫn hiển thị sáng / chiều mặc dù thời gian được đặt thành 24h trong cài đặt ngôn ngữ của máy tính
vir chúng tôi

20

Bạn có thể dùng new Date().getTimezoneOffset()/60 cho múi giờ. Cũng có mộttoLocaleString() phương pháp để hiển thị một ngày bằng cách sử dụng ngôn ngữ của người dùng.

Đây là toàn bộ danh sách: Làm việc với Ngày


toLocaleString cực kỳ không đáng tin cậy để trình bày ngày theo định dạng mà người dùng có thể mong đợi. Ngay cả khi ISO 402 được hỗ trợ, nó vẫn rất không đáng tin cậy và dựa trên định dạng của ngôn ngữ chứ không phải ngôn ngữ.
RobG

@RobG giải pháp thay thế là toLocaleStringgì?
dùng924

@ user924, bạn có thể sử dụng một thư viện, có rất nhiều lựa chọn. Vấn đề với toLocaleString là các triển khai khác nhau cho kết quả khác nhau với các mức hỗ trợ khác nhau cho các ngôn ngữ và khu vực khác nhau. Ví dụ: ngôn ngữ mặc định hệ thống của tôi không phải là en-US nhưng định dạng mặc định cho toLocaleString cho một số trình duyệt là định dạng của Hoa Kỳ, những ngôn ngữ khác tôn trọng ngôn ngữ hệ thống của tôi. Nó giống với tên múi giờ, chỉ tệ hơn khi chúng không được chuẩn hóa. :-(
RobG

7

Khi bạn đã xây dựng đối tượng ngày của mình, đây là đoạn trích cho chuyển đổi:

Hàm lấy một đối tượng Ngày định dạng UTC và chuỗi định dạng.
Bạn sẽ cần một Date.strftimenguyên mẫu.

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

    return d.strftime(format);
}

6
bạn đã rời đi từ đâu?
Anuj Pandey

Việc đặt giờ có ảnh hưởng gì đến các phần Ngày / Ngày / Năm của đối tượng Ngày không? Có vẻ như không.
ChristoKiwi

1
@ ChristoKiwi, giá trị được chuyển cho setHours dự kiến ​​là một số nguyên getTimezoneOffset()/60có thể trả về một phần (ví dụ: Ấn Độ bù +05: 30 sẽ trả về 5,5). Số thập phân được cắt ngắn. Mặt khác, đặt giờ sẽ cập nhật các giá trị khác (đặt giờ thành 48 và xem điều gì xảy ra).
RobG

7

Trong JS không có cách đơn giản và đa nền tảng nào để định dạng thời gian ngày cục bộ, ngoài việc chuyển đổi từng thuộc tính như đã đề cập ở trên.

Đây là một bản hack nhanh mà tôi sử dụng để lấy YYYY-MM-DD cục bộ. Lưu ý rằng đây là một hack, vì ngày cuối cùng sẽ không có múi giờ chính xác nữa (vì vậy bạn phải bỏ qua múi giờ). Nếu tôi cần bất cứ điều gì khác, tôi sử dụng khoảnh khắc.

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.getTimezone Offerset () trả về độ lệch múi giờ tính bằng phút và d.getTime () tính bằng ms, do đó x 60.000.


1
@VG Tôi đã thêm một số thông tin về việc 60k đến từ đâu. Hy vọng điều này giúp đỡ.
Jeremy Chone

5

Đây là những gì tôi đã sử dụng trong các dự án trước đây:

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
Đây là với công cụ cụ thể ASP.NET.
ZiggyTheroulette 7/214

Độ lệch múi giờ không nhất thiết là bội số của một giờ, do đó, getTimezoneOffset()/60thường sẽ trả về giá trị thập phân. Điều này đặc biệt đúng với những ngày trước năm 1900, nơi nhiều nơi đã bù đắp trong vài phút và giây. Ngoài ra, ngày javascript hiện được yêu cầu để hỗ trợ bù đắp lịch sử. Ví dụ, vào năm 1890, phần bù ở Moscow là +2: 30: 17. Xem Trình duyệt, múi giờ, Lỗi Chrome 67 .
RobG

3

Các .getTimezoneOffset()phương pháp báo cáo múi giờ bù đắp trong vài phút, đếm "về phía tây" từ múi giờ GMT / UTC, kết quả là một giá trị bù đắp đó là tiêu cực đến những gì người ta thường quen với việc. (Ví dụ: thời gian ở New York sẽ được báo cáo là +240 phút hoặc +4 giờ)

Để có được độ lệch múi giờ bình thường tính bằng giờ, bạn cần sử dụng:

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

Chi tiết quan trọng:
Lưu ý rằng thời gian tiết kiệm ánh sáng ban ngày được tính vào kết quả - vì vậy những gì phương pháp này mang lại cho bạn thực sự là thời gian bù - không phải là bù theo múi giờ địa lý thực tế .


3

Với ngày từ mã PHP tôi đã sử dụng một cái gì đó như thế này ..

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

Chúng ta có thể gọi nó như thế này

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

Câu hỏi là về JavaScript, không phải PHP.
pipedreambomb

5
Câu trả lời chỉ có trong javascript, Nó được đề cập trong câu hỏi rằng ngày máy chủ là trong UTC. vì vậy máy chủ có thể ở bất kỳ ngôn ngữ nào. vì vậy tôi chỉ trả lời cho PHP
hriziya

3

Tôi trộn các câu trả lời cho đến nay và thêm vào đó, bởi vì tôi phải đọc tất cả chúng và điều tra thêm một lúc để hiển thị chuỗi thời gian ngày từ db theo định dạng múi giờ cục bộ của người dùng.

Chuỗi datetime đến từ một python / django db ở định dạng: 2016-12-05T15: 12: 24.215Z

Phát hiện đáng tin cậy ngôn ngữ trình duyệt trong JavaScript dường như không hoạt động trong tất cả các trình duyệt (xem JavaScript để phát hiện tùy chọn ngôn ngữ trình duyệt ), vì vậy tôi nhận ngôn ngữ trình duyệt từ máy chủ.

Python / Django: gửi ngôn ngữ trình duyệt yêu cầu làm tham số ngữ cảnh:

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

HTML: viết nó trong một đầu vào ẩn:

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

JavaScript: nhận giá trị của đầu vào ẩn, ví dụ en-GB, en-US; q = 0.8, en; q = 0.6 / và sau đó chỉ sử dụng ngôn ngữ đầu tiên trong danh sách thông qua thay thế và biểu thức chính quy

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

JavaScript: chuyển đổi thành datetime và định dạng nó:

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

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

Kết quả là (ngôn ngữ trình duyệt là 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);


Để tham khảo: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ mẹo (Tôi cần optionsmột phần cho trường hợp của tôi)
Xenos

2

Giải pháp tốt nhất tôi gặp phải là tạo các thẻ [time display = "llll" datetime = "UTC TIME" /] và sử dụng javascript (jquery) để phân tích và hiển thị nó theo thời gian của người dùng.

http://momentjs.com/ Moment.js

sẽ hiển thị thời gian độc đáo.


2

Bạn có thể sử dụng thông tin sau, báo cáo độ lệch múi giờ từ GMT sau vài phút:

new Date().getTimezoneOffset();

Lưu ý: - hàm này trả về số âm.


1

getTimeZone Offerset () và toLocaleString phù hợp với công việc ngày cơ bản, nhưng nếu bạn cần hỗ trợ múi giờ thực, hãy xem TimeZone.js của mde .

Có một vài lựa chọn được thảo luận trong câu trả lời cho câu hỏi này


1

Để chuyển đổi ngày thành ngày cục bộ, hãy sử dụng phương thức toLocaleDateString ().

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

Để chuyển đổi thời gian thành giờ địa phương, hãy sử dụng phương thức toLocaleTimeString ().

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

-12

Không biết cách thực hiện miền địa phương, nhưng javascript là công nghệ phía máy khách.

usersLocalTime = new Date();

sẽ có thời gian và ngày tháng của khách hàng trong đó (như được báo cáo bởi trình duyệt của họ và bằng cách mở rộng máy tính họ đang ngồi). Sẽ rất đơn giản nếu bao gồm thời gian của máy chủ trong phản hồi và thực hiện một số phép toán đơn giản để bù thời gian đoán.

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.