Định dạng ngày trong múi giờ cụ thể


177

Tôi đang sử dụng Moment.js để phân tích và định dạng ngày trong ứng dụng web của mình. Là một phần của đối tượng JSON, máy chủ phụ trợ của tôi gửi ngày dưới dạng một phần nghìn giây từ kỷ nguyên UTC (bù đắp Unix).

Ngày phân tích cú pháp trong một múi giờ cụ thể rất dễ dàng - chỉ cần nối số nhận dạng múi giờ RFC 822 vào cuối chuỗi trước khi phân tích cú pháp:

// response varies according to your timezone
const m1 = moment('3/11/2012 13:00').utc().format("MM/DD HH:mm")

// problem solved, always "03/11 17:00"
const m2 = moment('3/11/2012 13:00 -0400').utc().format("MM/DD HH:mm")

console.log({ m1, m2 })
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>

Nhưng làm cách nào để định dạng một ngày trong múi giờ cụ thể ?

Tôi muốn kết quả nhất quán bất kể thời gian hiện tại của trình duyệt, nhưng tôi không muốn hiển thị ngày trong UTC.


2
Khoảnh khắc không hỗ trợ điều này, nhưng họ đang làm việc với nó. github.com/timrwood/moment/pull/671
Ben

5
Điều này chỉ nên làm việc. Nếu bạn chuyển khoảnh khắc một chuỗi thời gian bao gồm phần bù mong muốn, thì nó sẽ giữ lại phần bù đó và hiển thị thời gian cục bộ như đã cho, thay vì tự động điều chỉnh theo giờ cục bộ của trình duyệt. Nếu tôi muốn nó điều chỉnh theo giờ địa phương của trình duyệt, thì tôi sẽ cho nó thời gian UTC thay vì rõ ràng cho nó một phần bù để sử dụng. Ý tôi là ... tôi cho nó một sự bù đắp rõ ràng, tại sao về cơ bản nó lại ăn nó và thực hiện chuyển đổi thành trình duyệt riêng. Thiết kế khủng.
Triynko

Các khoản bù trừ @Triynko phải chịu mức tiết kiệm ánh sáng ban ngày, vì vậy, nó không luôn hoạt động như mong đợi.
Pinkpanther

1
Một cái gì đó liên quan đến điều này, tôi muốn in thời gian theo một định dạng cụ thể, ví dụ: 15 tháng 3 năm 2018 nhưng không thể tìm thấy chuỗi định dạng để làm điều này. Cái chung DD MMM, YYYYkhông hoạt động, khi tôi sử dụng nó như thế nào moment.tz("2018-02-15T14:20:00.000+0530", "Asia/Bangkok").format("DD MMM, YYYY"). Ai đó có thể chỉ cho tôi trong tài liệu mà tôi có thể tìm thấy tất cả các khóa để định dạng thời gian khi sử dụng api này.
pRmdk

@PramodKumar Có chuyện gì vậy? Điều đó cho "15 Feb, 2018". Ý của bạn là sử dụng chuỗi định dạng DD MMMM, YYYYđể lấy "15 February, 2018"?
quietmint

Câu trả lời:


248

Như đã chỉ ra trong câu trả lời của Manto , .utcOffset()là phương pháp được ưa thích kể từ thời điểm 2.9.0. Hàm này sử dụng phần bù thực từ UTC, không phải phần bù ngược (ví dụ: -240 cho New York trong DST). Các chuỗi bù trừ như "+0400" hoạt động giống như trước:

// always "2013-05-23 00:55"
moment(1369266934311).utcOffset(60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).utcOffset('+0100').format('YYYY-MM-DD HH:mm')

Cái cũ hơn .zone()như một setter đã không được dùng trong Moment.js 2.9.0. Nó chấp nhận một chuỗi chứa mã định danh múi giờ (ví dụ: "-0400" hoặc "-04: 00" trong -4 giờ) hoặc một số biểu thị số phút sau UTC (ví dụ: 240 cho New York trong DST).

// always "2013-05-23 00:55"
moment(1369266934311).zone(-60).format('YYYY-MM-DD HH:mm')
moment(1369266934311).zone('+0100').format('YYYY-MM-DD HH:mm')

Để làm việc với các múi giờ được đặt tên thay vì offset số, hãy bao gồm Múi giờ và sử dụng .tz()thay thế:

// determines the correct offset for America/Phoenix at the given moment
// always "2013-05-22 16:55"
moment(1369266934311).tz('America/Phoenix').format('YYYY-MM-DD HH:mm')

Tôi đã gặp sự cố với điều này thông qua lỗi "TypeError: Object 240 không có lỗi 'định dạng' phương thức. Tôi nhận ra vùng chỉ có sẵn dưới dạng setter trên phiên bản 2.1.0 trở lên của Moment.js (và tôi đã ở phiên bản cũ hơn). Cảm ơn!
Melinda Weathers

5
@ebi Theo mặc định, nó đã sử dụng múi giờ của trình duyệt. Để truy cập phần bù múi giờ của trình duyệt, hãy sử dụng .zone()như một getter, trả về số phút từ UTC (ví dụ: trả về 300 cho New York trong thời gian tiêu chuẩn).
quietmint

1
@EricCope Không, không hẳn. Tuy nhiên, bạn cũng có thể sử dụng .tz("America/Phoenix")nếu bạn bao gồm khoảnh khắc js.com / timezone . Tôi đã cập nhật câu trả lời với một ví dụ.
quietmint

1
Lưu ý rằng việc sử dụng offset sẽ không hoạt động như mong đợi nếu múi giờ có độ lệch khác nhau do tiết kiệm ánh sáng ban ngày.
Pinkpanther

1
.Tutc Offerset () sẽ tự động quản lý thời gian tiết kiệm ánh sáng ban ngày? giống như khi tôi đặt UTC +1 CET vào mùa đông, nó có đặt cược UTC +2 CEST trong thời gian tiết kiệm ánh sáng ban ngày không? Nguyên nhân này làm cho nó có thể sử dụng được hay không!
haemse

61

Sử dụng múi giờ

moment(date).tz('Europe/Berlin').format(format)

Trước khi có thể truy cập một múi giờ cụ thể, bạn sẽ cần tải nó như vậy (hoặc sử dụng các phương pháp thay thế được mô tả ở đây )

moment.tz.add('Europe/Berlin|CET CEST CEMT|-10 -20 -30')

Tôi không nghĩ rằng thời điểm tz có sẵn khi câu hỏi được hỏi, nhưng tôi nghĩ rằng đây có thể là con đường để đi. Tôi hiện đang làm việc với một vấn đề tương tự với tất cả các dấu thời gian được lưu dưới dạng UTC trong MySQL, nhưng để được xem trong một vùng cụ thể phụ thuộc vào cấu hình người dùng chứ không phải múi giờ của máy khách.
nickdnk

47

Một vài câu trả lời đã đề cập rằng múi giờ này là cách để đi với múi giờ được đặt tên. Tôi chỉ muốn làm rõ điều gì đó về thư viện này khá khó hiểu với tôi. Có một sự khác biệt giữa hai tuyên bố này:

moment.tz(date, format, timezone)

moment(date, format).tz(timezone)

Giả sử rằng múi giờ không được chỉ định trong ngày đã qua:

Mã đầu tiên lấy ngày và giả sử múi giờ là mã được truyền vào. Mã thứ hai sẽ lấy ngày, giả sử múi giờ từ trình duyệt và sau đó thay đổi thời gian và múi giờ theo múi giờ được truyền vào.

Thí dụ:

moment.tz('2018-07-17 19:00:00', 'YYYY-MM-DD HH:mm:ss', 'UTC').format() // "2018-07-17T19:00:00Z"

moment('2018-07-17 19:00:00', 'YYYY-MM-DD HH:mm:ss').tz('UTC').format() // "2018-07-18T00:00:00Z"

Múi giờ của tôi là +5 từ utc. Vì vậy, trong trường hợp đầu tiên, nó không thay đổi và nó đặt ngày và giờ để có múi giờ utc.

Trong trường hợp thứ hai, nó giả sử ngày được truyền vào là -5, sau đó biến nó thành UTC và đó là lý do tại sao nó phát ra ngày "2018-07-18T00: 00: 00Z"

LƯU Ý: Tham số định dạng là thực sự quan trọng. Nếu khoảnh khắc bị bỏ qua có thể rơi trở lại lớp Date có thể có những hành vi không thể đoán trước


Giả sử múi giờ được chỉ định vào ngày được thông qua:

Trong trường hợp này cả hai cư xử như nhau


Mặc dù bây giờ tôi đã hiểu tại sao nó hoạt động theo cách đó, tôi nghĩ rằng đây là một tính năng khá khó hiểu và đáng để giải thích.


1
thời điểm (...). tz không phải là một hàm
K - Độc tính trong SO đang tăng lên.

5
Bạn đã cài đặt múi giờ?
Nicola Pedretti

Có cách nào để lấy lại khoảnh khắc được phân tích cú pháp và chuyển đổi mà không cần định dạng không? Ví dụ, nếu tôi muốn định dạng các cách khác nhau mà không phân tích lại tất cả.
jEremyB

Cảm ơn bạn đã làm rõ điều này - Tôi đã gặp sự cố khi đặt múi giờ khác với múi giờ trình duyệt của người dùng và đây là vấn đề chính xác.
Robin Schaaf

20

.zone () đã không được chấp nhận và thay vào đó, bạn nên sử dụng utc Offerset:

// for a timezone that is +7 UTC hours
moment(1369266934311).utcOffset(420).format('YYYY-MM-DD HH:mm')

8

Tôi đã gặp vấn đề tương tự với Moment.js. Tôi đã cài đặt múi giờ, nhưng vấn đề chưa được giải quyết. Sau đó, tôi đã làm những gì ở đây, nó hiển thị múi giờ và nó hoạt động như một bùa mê:

moment(new Date({your_date})).zone("+08:00")

Cảm ơn rất nhiều!


16
Bạn không nên sử dụng hàm new Date()tạo. Khoảnh khắc cung cấp mọi thứ bạn cần để phân tích ngày. Xem tài liệu phân tích cú pháp .
quietmint

Có, nhưng nếu tôi không làm điều đó, tôi sẽ nhận được một cảnh báo từ Khoảnh khắc, rằng nó không được chấp nhận bởi một thứ như thế
facundofarias

7
Cảnh báo có nghĩa là Moment đang quay trở lại chính xác những gì bạn đang làm (sử dụng new Date()nội bộ), nhưng điều này không nhất quán trên các trình duyệt . Thay vào đó, bạn nên sử dụng cung cấp định dạng dự kiến ​​làm đối số thứ hai. Ví dụ : moment("12-25-1995", "MM-DD-YYYY").
quietmint

4

Chỉ cần acreoss này, và vì tôi có cùng một vấn đề, tôi chỉ đăng kết quả mà tôi đã đưa ra

khi phân tích cú pháp, bạn có thể cập nhật phần bù (tức là tôi đang phân tích dữ liệu (1.1.2014) và tôi chỉ muốn ngày, ngày 1 tháng 1 năm 2014. Vào GMT + 1 tôi sẽ nhận được 31.12.2013. Vì vậy, tôi đã bù giá trị trước.

moment(moment.utc('1.1.2014').format());

Vâng, có ích cho tôi để hỗ trợ trên các múi giờ

B


-7

Bạn có thể thử cái này

Tại đây bạn có thể lấy ngày dựa trên múi giờ của khách hàng (Trình duyệt).

moment(new Date().getTime()).zone(new Date().toString().match(/([-\+][0-9]+)\s/)[1]).format('YYYY-MM-DD HH:mm:ss')

Regex về cơ bản giúp bạn có giá trị bù.

Chúc mừng !!


Thông thường, khoảnh khắc cung cấp cho bạn mọi thứ bạn cần. Bạn không bao giờ cần phải phù hợp với bất cứ điều gì tùy chỉnh.
Mahesh Samudra
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.