Làm cách nào để có Dấu thời gian UTC trong JavaScript?


157

Trong khi viết một ứng dụng web, việc lưu trữ (phía máy chủ) tất cả các thời gian trong DB là dấu thời gian UTC.

Tôi đã rất ngạc nhiên khi tôi nhận thấy rằng bạn thực sự không thể làm gì nhiều về mặt thao túng múi giờ trong JavaScript.

Tôi mở rộng đối tượng Date một chút. Liệu chức năng này có ý nghĩa? Về cơ bản, mỗi khi tôi gửi bất cứ thứ gì đến máy chủ, nó sẽ là dấu thời gian được định dạng với chức năng này ...

Bạn có thể thấy bất kỳ vấn đề lớn ở đây? Hoặc có thể là một giải pháp từ một góc độ khác nhau?

Date.prototype.getUTCTime = function(){ 
  return new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime(); 
}

Nó chỉ có vẻ hơi phức tạp với tôi. Và tôi cũng không chắc về hiệu suất.


Tôi biết đây là một câu hỏi cũ, nhưng cố gắng không mở rộng các đối tượng gốc như đối tượng Date. Ủng hộ vì tôi thích chính câu hỏi
phân tích

Date.parse (Ngày mới (). ToUTCString ())
Sagi

25
Đây là một câu hỏi cũ xuất hiện trong nguồn cấp dữ liệu của tôi ngày hôm nay và nó chứa đầy thông tin sai lệch. Dấu thời gian luôn ở trong UTC. new Date().toString()sẽ hiển thị cho bạn biểu diễn múi giờ hiện tại, new Date().toUTCString()sẽ hiển thị cho bạn đại diện thời gian UTC, nhưng luônnew Date().getTime()UTC , vì đó là thời gian Unix được định nghĩa là: "Thời gian Unix (còn được gọi là thời gian POSIX hoặc thời gian kỷ nguyên) là một hệ thống để mô tả nội dung trong thời gian, được định nghĩa là số giây đã trôi qua kể từ 00:00:00 Giờ quốc tế phối hợp (UTC), Thứ Năm, ngày 1 tháng 1 năm 1970, không tính giây nhuận. "
Amadan

Câu trả lời:


155
  1. Ngày được xây dựng theo cách đó sử dụng múi giờ địa phương, làm cho ngày xây dựng không chính xác. Để đặt múi giờ của một đối tượng ngày nhất định là xây dựng nó từ chuỗi ngày bao gồm múi giờ. (Tôi gặp vấn đề khi làm việc đó trong trình duyệt Android cũ hơn.)

  2. Lưu ý rằng getTime()trả về mili giây, không phải giây đơn giản.

Đối với dấu thời gian UTC / Unix, những điều sau đây phải đủ:

Math.floor((new Date()).getTime() / 1000)

Nó sẽ tính hệ số múi giờ hiện tại vào kết quả. Đối với một đại diện chuỗi, câu trả lời của David Ellis hoạt động.

Làm rõ:

new Date(Y, M, D, h, m, s)

Đầu vào đó được coi là giờ địa phương . Nếu thời gian UTC được thông qua, kết quả sẽ khác. Quan sát (Tôi đang ở GMT +02: 00 ngay bây giờ và là 07:50):

> var d1 = new Date();
> d1.toUTCString();
"Sun, 18 Mar 2012 05:50:34 GMT" // two hours less than my local time
> Math.floor(d1.getTime()/ 1000)
1332049834 

> var d2 = new Date( d1.getUTCFullYear(), d1.getUTCMonth(), d1.getUTCDate(), d1.getUTCHours(), d1.getUTCMinutes(), d1.getUTCSeconds() );
> d2.toUTCString();
"Sun, 18 Mar 2012 03:50:34 GMT" // four hours less than my local time, and two hours less than the original time - because my GMT+2 input was interpreted as GMT+0!
> Math.floor(d2.getTime()/ 1000)
1332042634

Cũng lưu ý rằng getUTCDate()không thể được thay thế cho getUTCDay(). Điều này là do getUTCDate()trả về ngày trong tháng ; trong khi đó, getUTCDay()trả về các ngày trong tuần .


1
1) Tôi đã không xây dựng một ngày ... Tôi đã thêm một chức năng nguyên mẫu hoạt động trên này . 2) Điểm hay, tôi nên thực hiện Math.floor / 1000 - nhưng tôi vẫn cần chức năng đó để có dấu thời gian UTC của một đối tượng ngày hiện tại ... phải không?
Merc

@Merc: 1) bạn đang gọi new Date(), điều đó tạo ra một ngày mới từ đầu vào UTC của bạn nhưng coi đó là ngày / giờ địa phương. 2) Có, bạn nên sử dụng Math.floor(this.getTime() / 1000)trong trường hợp này.
Bộ giải mã

Trả lời ở đây vì tôi cần cập nhật mã ... Đây là để có dấu thời gian Unix trong UTC cho một ngày hiện có : function () {return Math.floor (Ngày mới (this.getUTCFullYear (), this.getUTCMonth (), this.getUTCDate (), this.getUTCHours (), this.getUTCMinutes (), this.getUTCSeconds ()) .getTime () / 1000); } Điều này có nghĩa là tôi có thể làm: var n = Ngày mới (2008,10,10) ... ... n.getUTCTime (); (Điều này sẽ KHÁC BIỆT đến n.getUTCTime ())
Merc

1
Cảm ơn Bro Tập tin hoạt động của nó Math.floor ((ngày mới ()). GetTime () / 1000)
Manoj Patel

51

Bạn cũng có thể làm điều đó bằng cách sử dụng getTimezone Offerset và getTime,

x = new Date()
var UTCseconds = (x.getTime() + x.getTimezoneOffset()*60*1000)/1000;

console.log("UTCseconds", UTCseconds)


4
Cảm ơn, đây là nơi không thể tìm thấy trên internet!
Theofanis Pantelides

Tôi kiểm tra các mã sau : var tt = new Date('Thu Jan 01 1970 08:00:00 GMT+0800 (China Standard Time)'); (tt.getTime() - tt.getTimezoneOffset()*60*1000)/1000. Có vẻ như tt.getTime() - tt.getTimezoneOffset()là chính xác cho GMT+0800.
zangw

1
Điều này tốt hơnvar UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60)
StefansArya

Có vẻ như điều này không hoạt động như được viết .. Có vẻ như bạn phải truyền chuỗi thời gian vào new Date()đó bao gồm múi giờ..những gì mà đánh bại mục đích cố gắng thực hiện nó trong js ..
claudekennilol

Đây chỉ đơn giản là sai, giá trị giao cho UTCseconds không UTC giây .. giá trị thời gian Một ngày của UTC, thay đổi nó bằng bất cứ phương pháp phương tiện nó đại diện cho một thời điểm khác nhau trong thời gian.
RobG

34

Cách dễ nhất để có được thời gian UTC theo định dạng thông thường như sau:

new Date().toISOString()
"2016-06-03T23:15:33.008Z"

3
Đây là câu trả lời chính xác. Rất nhiều câu trả lời khác đưa ra "chuỗi thời gian phổ quát" nhưng không đưa ra "thời gian phối hợp phổ quát" hiện tại. Tôi không hiểu tại sao mọi thứ quá phức tạp ở đây.
gburton

Cảm ơn bạn @gburton. Đánh giá cao bạn thấy cách đơn giản để sự thật. :)
Tahsin Turkoz

1
Tôi sử dụng cái này, cùng với ".split ('T') [0]" để so sánh dựa trên ngày YYYY-MM-DD dễ dàng.
Sean O

Rất vui khi có @SeanO
Tahsin Turkoz

Điều này cung cấp chuỗi thời gian UTC, nhưng OP đang yêu cầu dấu thời gian UTC (epoch)
Jordi Nebot

13

Tôi thực sự nghĩ rằng giá trị Date trong js tốt hơn nhiều so với việc nói các đối tượng DateTime C #. Các đối tượng DateTime C # có thuộc tính Kind, nhưng không có múi giờ cơ bản nghiêm ngặt như vậy và các chuyển đổi múi giờ rất khó theo dõi nếu bạn đang chuyển đổi giữa hai thời gian không UTC và không cục bộ. Trong js, tất cả các giá trị Ngày đều có giá trị UTC cơ bản được truyền qua và được biết bất kể chuyển đổi múi giờ hay múi giờ mà bạn thực hiện. Khiếu nại lớn nhất của tôi về đối tượng Date là số lượng hành vi không xác định mà những người triển khai trình duyệt đã chọn đưa vào, điều này có thể khiến những người tấn công ngày trong js bị thử và mắc lỗi hơn là đọc thông số kỹ thuật. Sử dụng một cái gì đó như iso8601.js sẽ giải quyết hành vi thay đổi này bằng cách xác định một triển khai duy nhất của đối tượng Date.

Theo mặc định, thông số kỹ thuật cho biết bạn có thể tạo ngày với định dạng ngày mở rộng ISO 8601 như

var someDate = new Date('2010-12-12T12:00Z');

Vì vậy, bạn có thể suy ra thời gian UTC chính xác theo cách này.

Khi bạn muốn chuyển giá trị Ngày trở lại máy chủ, bạn sẽ gọi

someDate.toISOString();

hoặc nếu bạn muốn làm việc với dấu thời gian một phần nghìn giây (số mili giây từ UTC ngày 1 tháng 1 năm 1970)

someDate.getTime();

ISO 8601 là một tiêu chuẩn. Bạn không thể nhầm lẫn về ý nghĩa của chuỗi ngày nếu bạn bao gồm phần bù ngày. Điều này có nghĩa đối với bạn với tư cách là một nhà phát triển là bạn không bao giờ phải tự mình xử lý các chuyển đổi theo giờ địa phương . Các giá trị thời gian cục bộ tồn tại hoàn toàn vì lợi ích của người dùng và giá trị ngày theo mặc định hiển thị theo giờ địa phương của họ. Tất cả các thao tác thời gian cục bộ cho phép bạn hiển thị một cái gì đó hợp lý cho người dùng và chuyển đổi chuỗi từ đầu vào của người dùng. Đó là một thực tiễn tốt để chuyển đổi sang UTC ngay khi bạn có thể và đối tượng js Date làm cho điều này khá tầm thường.

Mặt khác, không có nhiều phạm vi để buộc múi giờ hoặc miền địa phương cho khách hàng (mà tôi biết), điều này có thể gây khó chịu cho các cài đặt dành riêng cho trang web, nhưng tôi đoán lý do đằng sau đây là do người dùng cấu hình không nên chạm vào.

Vì vậy, trong ngắn hạn, lý do không có nhiều hỗ trợ riêng cho thao tác múi giờ là vì đơn giản là bạn không muốn thực hiện nó.


12

Nói chung, bạn không cần phải thực hiện nhiều "Thao tác múi giờ" ở phía máy khách. Theo quy định, tôi cố gắng lưu trữ và làm việc với các ngày UTC, dưới dạng tickshoặc " số mili giây kể từ nửa đêm ngày 1 tháng 1 năm 1970 ". Điều này thực sự đơn giản hóa việc lưu trữ, sắp xếp, tính toán bù đắp và hơn hết là giúp bạn hết đau đầu trong việc điều chỉnh "Thời gian tiết kiệm ánh sáng ban ngày". Đây là một mã JavaScript nhỏ mà tôi sử dụng.

Để có được thời gian UTC hiện tại:

function getCurrentTimeUTC()
{
    //RETURN:
    //      = number of milliseconds between current UTC time and midnight of January 1, 1970
    var tmLoc = new Date();
    //The offset is in minutes -- convert it to ms
    return tmLoc.getTime() + tmLoc.getTimezoneOffset() * 60000;
}

Sau đó, những gì bạn thường cần là định dạng ngày / giờ cho người dùng cuối cho định dạng và múi giờ địa phương của họ . Sau đây sẽ giải quyết tất cả sự phức tạp của các định dạng ngày và giờ trên máy khách:

function formatDateTimeFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date/time
    return new Date(nTicks).toLocaleString();
}

function formatDateFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted date
    return new Date(nTicks).toLocaleDateString();
}

function formatTimeFromTicks(nTicks)
{
    //'nTicks' = number of milliseconds since midnight of January 1, 1970
    //RETURN:
    //      = Formatted time
    return new Date(nTicks).toLocaleTimeString();
}

Vì vậy, ví dụ sau:

var ticks = getCurrentTimeUTC();  //Or get it from the server

var __s = "ticks=" + ticks + 
    ", DateTime=" + formatDateTimeFromTicks(ticks) +
    ", Date=" + formatDateFromTicks(ticks) +
    ", Time=" + formatTimeFromTicks(ticks);

document.write("<span>" + __s + "</span>");

Trả về các mục sau (đối với ngôn ngữ tiếng Anh Mỹ của tôi):

ticks = 1409103400661, DateTime = 8/26/2014 6:36:40 PM, Ngày = 8/26/2014, Thời gian = 6: 36: 40 PM


1
Bằng cách thêm getTimezoneOffsetgiá trị trong getCurrentTimeUTChàm của bạn , bạn thực sự trả về một thời điểm khác. Kết quả getTimeđã ở UTC.
Matt Johnson-Pint

1
@MattJohnson: Điều đó không chính xác. Kết quả tmLoc.getTime()là một sự bù đắp so với giờ địa phương. Điều đó thật dễ dàng để kiểm tra xem bạn có quyền truy cập vào bất cứ thứ gì chạy JavaScript hay không.
ahmd0

2
Xin lỗi, nhưng điều đó không đúng. Xem tài liệu tham khảo MDN . Bạn cũng có thể thấy điều này trong thông số ECMAScript. §15.9.3.3 mô tảgetTime , chỉ ra bạn ở "giá trị thời gian" được xác định trong §15.9.5 , là một PrimitiveValue, như được đặt trong §15.9.3.3 rõ ràng là UTC.
Matt Johnson-Pint

2
Vâng, vì bạn có được tmLocthông qua new Date(), sau đó là điều tương tự. Múi giờ sẽ ảnh hưởng đến đầu ra chuỗi của tmLoc.toString()các mặt hàng tương tự, nhưng nó sẽ không ảnh hưởng đến tmLoc.getTime() Điều đó luôn chỉ là một số mili giây kể từ nửa đêm 1970-01-01 trong UTC.
Matt Johnson-Pint

1
@StefansArya://The offset is in minutes -- convert it to ms
ahmd0

5

Tôi nghĩ rằng đây là một giải pháp tốt hơn

// UTC milliseconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()

// UTC seconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()/1000|0

Một câu trả lời sai khác, getTime trả về một bù UTC, thêm phần bù múi giờ cục bộ hoàn toàn làm nó rối tung lên. Các độ lệch ECMAScript là + ve cho hướng tây và -ve cho hướng đông, vì vậy chúng nên được trừ khỏi UTC để lấy địa phương. Nhưng vì giá trị thời gian là UTC để bắt đầu, việc thêm nó về cơ bản sẽ chuyển nó khỏi UTC theo hướng ngược lại với bù cục bộ.
RobG

4

Nếu bạn muốn có một lớp lót , Dấu thời gian Unix UTC có thể được tạo bằng JavaScript như:

var currentUnixTimestap = ~~(+new Date() / 1000);

Điều này sẽ tính đến múi giờ của hệ thống. Về cơ bản là thời gian trôi qua trong giây kể từ kỷ nguyên.

Làm thế nào nó hoạt động:

  • Tạo đối tượng ngày : new Date().
  • Chuyển đổi thành dấu thời gian bằng cách thêm unary +trước khi tạo đối tượng để chuyển đổi nó thành timestamp integer. : +new Date().
  • Chuyển đổi mili giây thành giây: +new Date() / 1000
  • Sử dụng dấu ngã kép để làm tròn giá trị thành số nguyên. :~~(+new Date())

7
tilde, không phải tilda(sic). Đáng buồn thay, nó sẽ không cho phép tôi xóa một lỗi đánh máy, tôi phải thực hiện ít nhất 6 lần chỉnh sửa ký tự. Mượt, Stackexchange, trơn tru
Fred

3
Không sử dụng cái này . Với thông số kỹ thuật ecma hiện tại, các thao tác bitwise (như dấu ngã - bitwise không) xử lý các giá trị nguyên đã ký là 32 bit. Điều đó có nghĩa là phép thuật dấu ngã này sẽ không hoạt động sau 19 tháng 1 năm 2038 khi giá trị dấu thời gian sẽ vượt quá giá trị tối đa của một số nguyên có chữ ký 32 bit. jsfiddle.net/phb20ymb
Sharky

3

Tôi muốn làm rõ rằng Date (). GetTime () mới thực tế trả về giá trị UTC, vì vậy đây là một cách thực sự hữu ích để lưu trữ và quản lý ngày theo cách không thể tin được theo thời gian địa phương hóa.

Nói cách khác, đừng bận tâm với tất cả các chức năng javascript của UTC. Thay vào đó, chỉ cần sử dụng Date.getTime ().

Thông tin thêm về lời giải thích có tại đây: Nếu javascript "(ngày mới ()). GetTime ()" được chạy từ 2 múi giờ khác nhau.


3

Tôi sử dụng như sau:

Date.prototype.getUTCTime = function(){ 
  return this.getTime()-(this.getTimezoneOffset()*60000); 
};

Sau khi xác định phương pháp này, bạn có thể làm:

var utcTime = new Date().getUTCTime();

Giải pháp sạch nhất. CÁM ƠN!
tuyết

Nhưng đó không phải là một giải pháp sạch để gửi ngày, vì TimeStamp luôn là UTC. Giải pháp tốt nhất cho tôi khi gửi ngày, là sử dụng biểu diễn chuỗi như "dd / MM / yyyy HH: mm: ss" và sau đó phân tích nó ở phía máy chủ với TimeZone mặc định của máy chủ để lấy dấu thời gian UTC hoặc bất cứ điều gì. Xem câu trả lời
jlbofh

2
phân tích một chuỗi - bạn đang gọi đó là sạch? meh
avalanche1

Hãy chắc chắn, có các phương pháp để tạo một ngày ở định dạng chuỗi theo thông số kỹ thuật của ISO. Phương thức này là toISOString (). Bạn có thể phân tích cú pháp một cách sạch sẽ trong Java bằng cách sử dụng một cái gì đó như:DateTime dt = new DateTime ("2018-07-15T02:36:00+02:00");
jlbofh

Một câu trả lời sai khác, this.getTime()trả về một phần bù UTC, trừ phần bù múi giờ cục bộ làm cho nó trở thành cục bộ, không phải UTC vì vậy getUTCTime trả về phần bù cục bộ, không phải UTC.
RobG

2

Tôi ngạc nhiên về mức độ phức tạp của câu hỏi này.

Tất cả đều giống nhau và tất cả các giá trị nguyên của chúng === thời gian EPOCH: D

console.log((new Date()).getTime() / 1000, new Date().valueOf() / 1000, (new Date() - new Date().getTimezoneOffset() * 60 * 1000) / 1000);

Đừng tin tôi, hãy kiểm tra: http://www.epochconverter.com/


2

new Date().toUTCString()trả về một chuỗi như "Wed, 11 Oct 2017 09:24:41 GMT"bạn có thể cắt 3 ký tự cuối cùng và chuyển chuỗi được cắt thành new Date():

new Date()
// Wed Oct 11 2017 11:34:33 GMT+0200 (CEST)

new Date(new Date().toUTCString().slice(0, -3))
// Wed Oct 11 2017 09:34:33 GMT+0200 (CEST)

1

EDIT: Mã dưới đây KHÔNG hoạt động. Tôi đã luôn luôn giả định rằng Ngày mới (). GetTime () đã trả về số giây kể từ ngày 1 tháng 1 năm 1970 TRONG THỜI GIAN HIỆN TẠI. Đây không phải là trường hợp: getTime () trả về số giây trong UTC. Vì vậy, mã dưới đây không điều chỉnh quá mức. Cám ơn mọi người!]

Trước hết, cảm ơn bạn cho những hiểu biết tuyệt vời của bạn. Tôi đoán câu hỏi của tôi có tiêu đề sai ... nên là "Lấy dấu thời gian Unix UTC cho một ngày hiện tại".

Vì vậy, nếu tôi có một đối tượng ngày:

var d = new Date(2009,01,31)

Tôi đã theo dõi một chức năng sẽ cho tôi biết "Dấu thời gian Unix UTC".

Chức năng này có vẻ là mẹo thực sự:

Date.prototype.getUTCUnixTime =  function (){
  return Math.floor( new Date(
    this.getUTCFullYear(),
    this.getUTCMonth(),
    this.getUTCDate(),
    this.getUTCHours(),
    this.getUTCMinutes(), 
    this.getUTCSeconds()
  ).getTime() / 1000); 
}

Lưu ý rằng nó hoạt động trên "này" Điều này có nghĩa là tôi có thể làm:

var n = new Date(2008,10,10)
...
...

n.getUTCUnixTime();

Và lấy số giây kể từ ngày 1 tháng 1 năm 1970 trong thời gian Unix. Đúng?

Đối với tôi, điều đó hơi điên rồ, Javascript lưu trữ mọi thứ trong thời gian UTC, nhưng sau đó để có được số đó, tôi phải tạo một đối tượng Date mới thông qua các getters UTC riêng lẻ và cuối cùng gọi getTime () cho ...

Merc.


1
Bạn có thấy @ DCoder cập nhật câu trả lời của anh ấy không? Phương pháp của bạn getUTCUnixTimebị sai thời gian, và JavaScript không cung cấp một cách đơn giản để có được những dấu thời gian unix từ một Dateđối tượng - bằng cách sử dụng getTimephương pháp. Xem tất cả các câu trả lời khác.
Anurag

1
Ugh bạn đúng, chỉ cần nhìn thấy họ. (Đập đầu vào tường)
Merc

1

Tôi nghĩ đây là những gì bạn đang mong đợi ...

var currTimestamp = Date.now(), //1482905176396
    utcDateString = (new Date(currTimestamp)).toUTCString(); //"Wed, 28 Dec 2016 06:06:50 GMT"

Hiện nay,

new Date(utcDateString).getTime(); //This will give you UTC Timestamp in JavaScript


0

Sử dụng day.js

Trong trình duyệt:

dayjs.extend(dayjs_plugin_utc)
console.log(dayjs.utc().unix())
<script src="https://cdn.jsdelivr.net/npm/dayjs@latest/dayjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dayjs@latest/plugin/utc.js"></script>

Trong node.js:

import dayjs from 'dayjs'
dayjs.extend(require('dayjs/plugin/utc'))
console.log(dayjs.utc().unix())

Bạn nhận được dấu thời gian unix UTC không có mili giây.


-2

Điều này sẽ trả về dấu thời gian trong UTC:

var utc = new Date(new Date().toUTCString()).getTime();


2
Điều này không trả lại thời gian trong UTC: new Date(new Date().toUTCString())cung cấp cho Thứ tư 04 tháng 10 năm 2017 07:20:14 GMT + 0200 (GMT + 02: 00)
Bas van Dijk
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.