2013-08-02 206 views
12

Hãy nói rằng người dùng trong CA, US nhặt một ngày, giờ và múi giờ:Cách chuyển đổi thời gian chính xác theo múi giờ?

Worldwide marathon bia bắt đầu từ ngày 2013/08/15 10:00, UTC-08: 00

Một người dùng khác , ở Trung Âu sẽ mở trang nơi ngày và giờ này được hiển thị. Anh ta không muốn tính toán thời gian (có ít bia). Ông chỉ muốn thấy ngày này và thời gian:

8/15/2013 19:00

Với trình duyệt nhận được thông tin cập nhật và thời gian, khi nhập vào bởi người sử dụng ở California:

Is có cách nào, trong javascript, không có dịch vụ web bên ngoài, để thực hiện chuyển đổi chính xác? Nghĩa là, để phát hiện 10 giờ UTC-08: 00 đó thực sự là 10 giờ sáng UTC-07: 00, vì đó là Daylight Saving.

Có lẽ tôi đã hiểu sai về điều này ngay từ đầu, nhưng tôi không muốn cho người dùng nhập suy nghĩ liệu anh ấy nên chọn UTC-08: 00 (PST) hoặc UTC-07: 00 (PDT). Tôi cho rằng vì múi giờ chuẩn trong CA là PST, nên mọi người không chuyển sang tư duy trong PDT trong thời gian mùa hè. Hay họ?

Ở trung tâm châu Âu, ngày chuẩn là UTC + 01: 00, ngày tiết kiệm ánh sáng ban ngày là UTC + 02: 00. Vì vậy, sự khác biệt giữa CA và châu Âu nên là 9 giờ, ngoại trừ hai giai đoạn trong một năm, khi một hoặc khu vực khác chuyển đổi giữa chế độ Standard và Daylight Saving.

Cập nhật:

Sau một vài suy nghĩ nhiều hơn và đọc các ý kiến, những gì tôi tưởng sẽ cần điều này là:

var utcOffset = f('2013-08-15T10:00', 'America/Los_Angeles'); 
// utcOffset == "-07:00" 
var utcOffset = f('2013-11-15T10:00', 'America/Los_Angeles'); 
// utcOffset == "-08:00" 

Cho đến nay, có vẻ như các moment.js/timezone plugin, được đề xuất bởi Guido Preite là có khả năng làm điều này (nhiều hơn hoặc ít hơn).

Bất kỳ cách nào khác, sử dụng API trình duyệt?

+1

kiểm tra 'Thời điểm.js' và 'Múi giờ thời gian 'http://momentjs.com/timezone/ –

+0

Tôi đã sử dụng moment.js. Tiện ích mở rộng múi giờ có vẻ đầy hứa hẹn. Tệp thời gian được tạo có chứa dữ liệu chuyển đổi Tiết kiệm ánh sáng ban ngày. Sau khi kiểm tra nhanh, nó có thể điều chỉnh chính xác thời gian đã nhập. Vì vậy, điều này có vẻ như các trình duyệt không thể nói "hey, cho ngày này bạn phải sử dụng bù đắp UTC này kể từ ngày đó, có thời gian mùa hè"? – rdamborsky

Trả lời

19

Có cách nào, trong javascript, mà không cần các dịch vụ web bên ngoài, để làm một chuyển đổi chính xác?Nghĩa là, để phát hiện 10 giờ UTC-08: 00 đó thực sự là 10 giờ sáng UTC-07: 00, vì đó là Daylight Saving.

10: 00-8 và 10: 00-7 là hai khoảnh khắc khác nhau đúng lúc. Chúng tương ứng với 18: 00Z và 17: 00Z tương ứng (Z = UTC). Khi bạn đang đo lường về một bù đắp, ánh sáng ban ngày tiết kiệm thời gian không nhập hình ảnh. Không bao giờ.

Tôi giả định rằng do múi giờ chuẩn trong CA là PST, mọi người không chuyển sang suy nghĩ trong PDT trong mùa hè. Hay họ?

Nói chung, mọi người chỉ nghĩ đến "Giờ Thái Bình Dương" và điều đó có nghĩa là cả PST vào mùa đông và PDT vào mùa hè. Nhưng máy tính chính xác hơn. Khi bạn thấy PST, nó có nghĩa là UTC-8. Khi bạn thấy PDT, nó có nghĩa là UTC-7. Nó sẽ là không hợp lệ để nhãn bằng cách sử dụng một hình thức trong khi đồng thời đề cập đến sự bù đắp của khác.

Cụm từ viết tắt của múi giờ can be ambiguous. Lý tưởng nhất, khi tham chiếu vùng theo lập trình, bạn nên sử dụng tên vùng IANA, chẳng hạn như America/Los_Angeles. Tuy nhiên, điều này hiện không thể thực hiện được trong tất cả các thời gian chạy JavaScript mà không có thư viện. (They are working on this though.)

Ở Trung Âu, ngày chuẩn là UTC + 01: 00, ngày tiết kiệm ánh sáng ban ngày là UTC + 02: 00. Vì vậy, sự khác biệt giữa CA và châu Âu nên là 9 giờ, ngoại trừ hai giai đoạn trong một năm, khi một hoặc khu vực khác chuyển đổi giữa chế độ Standard và Daylight Saving.

Đúng. Chúng có thể cách nhau 8, 9 hoặc 10 giờ. Họ chuyển đổi tại thời điểm hoàn toàn khác nhau mặc dù, do đó, không cố gắng để quản lý này cho mình.

Cho đến nay, nó trông giống như plugin thời gian/giây, do Guido Preite đề xuất có khả năng thực hiện việc này (nhiều hơn hoặc ít hơn).

Moment-timezone là một thư viện tuyệt vời. Tuy nhiên, từ kịch bản bạn mô tả, tôi không nghĩ bạn cần phải lo lắng về việc chuyển đổi múi giờ nhiều như bạn đang nghĩ. Xem liệu bạn có thể thực hiện theo logic này không:

  1. Người dùng ở California nhập ngày và giờ vào hộp văn bản.
  2. Bạn đọc rằng giá trị textbox vào một chuỗi, và phân tích nó thành một ngày:

    var dt = new Date("8/15/2013 10:00"); 
    

    hoặc sử dụng moment.js:

    var m = moment("8/15/2013 10:00", "M/D/YYYY HH:mm"); 
    
  3. Bởi vì đây đang được thực hiện trên máy tính của người dùng , JavaScript sẽ tự động giả định rằng đây là ngày địa phương ngày và giờ. Bạn không cần phải cung cấp bất kỳ thông tin bù trừ hoặc múi giờ nào.

  4. Điều này có nghĩa là do chuyển tiếp DST mà thời gian đã nhập có thể không hợp lệ hoặc không rõ ràng. JavaScript không thực hiện công việc tuyệt vời như vậy trong việc xử lý điều đó, trên thực tế - bạn sẽ nhận được các kết quả khác nhau trên các trình duyệt khác nhau. Nếu bạn muốn được rõ ràng, sau đó bạn sẽ cung cấp một bù đắp.

    // PST 
    var dt = new Date("3/11/2013 1:00 UTC-08:00"); 
    
    // PDT 
    var dt = new Date("3/11/2013 1:00 UTC-07:00"); 
    
  5. Một khi bạn có một Date (hoặc một moment), sau đó bạn có thể đánh giá UTC của nó tương đương:

    var s = dt.toISOString(); // 2013-08-15T17:00:00Z 
    

    nó giống với moment.js, nhưng bạn sẽ phải hỗ trợ trình duyệt tốt hơn:

    var s = m.toISOString(); // 2013-08-15T17:00:00Z 
    
  6. Bạn lưu trữ giá trị UTC đó trong cơ sở dữ liệu của mình.

  7. Người dùng khác ở Trung Âu đi cùng và tải dữ liệu.

  8. Bạn ăn nó vào một Date hay moment trong JavaScript:

    var dt = new Date("2013-08-15T17:00:00Z"); 
    

    hoặc với moment.js (một lần nữa, tốt hơn hỗ trợ trình duyệt)

    var m = moment("2013-08-15T17:00:00Z") 
    
  9. Bởi vì JavaScript biết múi giờ các quy tắc của máy tính cục bộ, bây giờ bạn có thể hiển thị ngày này và nó sẽ được trình bày theo múi giờ Trung Âu:

    var s = dt.ToString(); // browser specific output 
    // ex: "Thu Aug 15 2013 19:00:00 GMT+0200 (Central Europe Daylight Time)" 
    

    hoặc với moment.js, bạn có thể kiểm soát các định dạng đầu ra tốt hơn

    var s = m.format("DD/MM/YYYY HH:mm"); // "15/08/2013 19:00" 
    

    bạn cũng có thể để cho moment.js quyết định những gì định dạng cục bộ cần được đầu ra:

    var s = m.format("llll"); // "Thu, 15 Aug 2013 19:00" 
    

Để tóm tắt - nếu bạn chỉ quan tâm đến việc chuyển đổi đến và đi khỏi múi giờ địa phương (bất kỳ vùng nào có thể), thì bạn có thể làm tất cả chỉ với Date. Moment.js sẽ giúp mọi thứ dễ dàng hơn trong việc phân tích cú pháp và định dạng, nhưng nó không phải là hoàn toàn bắt buộc.

Chỉ có một vài trường hợp mà yêu cầu thư viện múi giờ (chẳng hạn như múi giờ hoặc những người khác).

  • Bạn muốn chuyển đổi đến hoặc từ một khu vực đó là không múi giờ địa phương hoặc UTC.

  • Bạn đang làm việc với các ngày đó là trong quá khứ, đã có một sự thay đổi các quy tắc múi giờ hoặc quy tắc ước giờ mùa hè kể từ đó, bạn có ngày đó sẽ được giải thích khác nhau dưới quy tắc mới hơn so với quy tắc cũ. Đây là một chút kỹ thuật, nhưng nó xảy ra. Đọc thêm herehere.

+0

Cảm ơn Matt, về thông tin, liên kết và hướng dẫn đầy đủ. Kịch bản của tôi chính xác là trường hợp đầu tiên bạn chỉ ra: chuyển đổi không phải là múi giờ địa phương. Tức là, người dùng nhập ngày giờ cũng vào múi giờ có liên quan đến thời gian đó. Điều này không nhất thiết phải là người dùng múi giờ. Tôi thấy tôi nên nêu rõ điều này trong câu hỏi. – rdamborsky

+0

Tôi sẽ nói rằng đó là vô lý mà javascript, lập trình ngôn ngữ của "thế giới web rộng" không có được xây dựng trong thời gian chuyển đổi/múi giờ công cụ –

1

Mặc định constructor tạo ra thể hiện của giờ địa phương

var localDate = new Date(); 

tôi không thể kiểm tra nó ngay bây giờ, nhưng bạn sẽ có thể cung cấp datetime của bạn (như một tham số để các nhà xây dựng) ..

var eventDate = [SOMEDATE]; 
var localDate = new Date(eventDate); 

..và sau đó bạn có thể gọi các hàm đối tượng ngày tháng như getMonth, trả về dữ liệu theo múi giờ địa phương. Như được viết tại: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

Lưu ý1: Không có máy chủ = không có máy chủ nào cả? Nếu có, ngày nên được lưu dưới dạng UTC trong db và tải nó dưới dạng giờ địa phương cho mọi người dùng .. theo cách đó bạn không phải lo lắng về chuyển đổi.

Note2: Câu hỏi này có một số mã cho thấy làm thế nào để có được múi giờ khác biệt: How to get the exact local time of client?

+0

Có, điều này thường hoạt động ok. Vấn đề là khi người dùng nhập múi giờ rõ ràng được sử dụng cho ngày được lưu. Hãy tưởng tượng bạn gửi 07/20/2013 10:00 UTC-08: 00 trong khi nghĩ về điều này như thời gian ở CA. Nhưng thông tin này là không chính xác, vì tại ngày đã cho -07: 00 nên được sử dụng để bù trừ. Và đây là những gì tôi cần để phát hiện và giải quyết. Phần lưu trữ/truy xuất dễ dàng sau khi ngày được lưu chính xác. Tôi muốn tránh quyết định giữa thời gian tiêu chuẩn/mùa hè trong giai đoạn bước vào. – rdamborsky

0

Tôi đã phát triển giải pháp này dựa trên các ví dụ khác ... hy vọng điều này phù hợp với bạn! Có sẵn trên jsfiddle.

/* 
* Author: Mohammad M. AlBanna 
* Website: MBanna.me 
* Description: Get the current time in different time zone 
*/ 

//Check daylight saving time prototype 
Date.prototype.stdTimezoneOffset = function() { 
    var jan = new Date(this.getFullYear(), 0, 1); 
    var jul = new Date(this.getFullYear(), 6, 1); 
    return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset()); 
} 

Date.prototype.dst = function() { 
    return this.getTimezoneOffset() < this.stdTimezoneOffset(); 
} 

var today = new Date(); 
var isDST = today.dst() ? true : false; 
var pstOffset = isDST ? 7 : 8; 
var cstOffset = isDST ? 5 : 6; 
var estOffset = isDST ? 4 : 5; 
var gmtOffset = 1; 

pstOffset = pstOffset * 60 * 60 * 1000; 
cstOffset = cstOffset * 60 * 60 * 1000; 
estOffset = estOffset * 60 * 60 * 1000; 
gmtOffset = gmtOffset * 60 * 60 * 1000; 

var todayMillis = today.getTime(); 
var timeZoneOffset = (today.getTimezoneOffset() * 60 * 1000); 

var curretPST = todayMillis - pstOffset; 
var curretCST = todayMillis - cstOffset; 
var curretEST = todayMillis - estOffset; 
var curretGMT = todayMillis - gmtOffset; 

addP("PST Time : " + new Date(curretPST).toUTCString()); 
addP("CST Time : " + new Date(curretCST).toUTCString()); 
addP("EST Time : " + new Date(curretEST).toUTCString()); 
addP("GMT Time : " + new Date(curretGMT).toUTCString()); 
addP("Local Time : " + new Date(today.getTime() - timeZoneOffset).toUTCString()); 

function addP(value){ 
    var p = document.createElement("p"); 
    p.innerHTML = value; 
    document.body.appendChild(p); 
}