Bagaimana saya mendapatkan cap waktu UTC dalam JavaScript?

158

Saat menulis aplikasi web, masuk akal untuk menyimpan (sisi server) semua data di DB sebagai cap waktu UTC.

Saya heran ketika saya perhatikan bahwa Anda tidak bisa melakukan banyak hal dalam hal manipulasi zona waktu di JavaScript.

Saya sedikit memperpanjang objek Date. Apakah fungsi ini masuk akal? Pada dasarnya, setiap kali saya mengirim sesuatu ke server, itu akan menjadi timestamp yang diformat dengan fungsi ini ...

Bisakah Anda melihat masalah besar di sini? Atau mungkin solusi dari sudut yang berbeda?

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

Sepertinya sedikit berbelit-belit bagi saya. Dan saya juga tidak begitu yakin dengan kinerja.

Merc
sumber
Saya tahu ini semacam pertanyaan lama, tetapi cobalah untuk tidak memperluas objek asli seperti objek Date. Terpilih karena saya suka pertanyaan itu sendiri.
trysis
Date.parse (Date baru (). ToUTCString ())
Sagi
26
Ini adalah pertanyaan lama yang muncul dalam umpan saya hari ini, dan penuh dengan informasi yang salah. Stempel waktu selalu dalam UTC. new Date().toString()akan menunjukkan waktu saat ini zona waktu representasi, new Date().toUTCString()akan menunjukkan waktu UTC cetak ulang, tapi new Date().getTime()ini selalu UTC , karena itulah yang saat Unix didefinisikan sebagai: "waktu Unix (juga dikenal sebagai waktu POSIX atau waktu zaman) adalah sistem untuk menggambarkan instants dalam waktu, didefinisikan sebagai jumlah detik yang telah berlalu sejak 00:00:00 Waktu Universal Terkoordinasi (UTC), Kamis, 1 Januari 1970, tidak termasuk detik kabisat. "
Amadan

Jawaban:

155
  1. Tanggal dibangun dengan cara itu menggunakan zona waktu lokal, membuat tanggal yang dibangun salah. Untuk mengatur zona waktu objek tanggal tertentu adalah dengan membangunnya dari string tanggal yang menyertakan zona waktu. (Saya punya masalah untuk membuatnya berfungsi di browser Android yang lebih lama.)

  2. Perhatikan bahwa getTime()pengembalian milidetik, bukan detik biasa.

Untuk cap waktu UTC / Unix, berikut ini sudah cukup:

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

Ini akan memasukkan faktor zona waktu saat ini ke dalam hasil. Untuk representasi string, jawaban David Ellis bekerja.

Untuk memperjelas:

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

Masukan itu diperlakukan sebagai waktu setempat . Jika waktu UTC dilewatkan, hasilnya akan berbeda. Amati (saya dalam GMT +02: 00 sekarang, dan ini 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

Perhatikan juga bahwa getUTCDate()tidak dapat diganti getUTCDay(). Ini karena getUTCDate()mengembalikan hari dalam sebulan ; sedangkan, getUTCDay()mengembalikan hari dalam seminggu .

DCoder
sumber
1
1) Saya tidak membuat tanggal ... Saya menambahkan fungsi prototipe yang berfungsi pada ini . 2) Poin bagus, saya harus melakukan Math.floor / 1000 - tetapi saya masih membutuhkan fungsi itu untuk memiliki stempel waktu UTC dari objek tanggal yang ada ... benar?
Merc
@Merc: 1) Anda menelepon new Date(), yang menciptakan tanggal baru dari input UTC Anda tetapi memperlakukannya sebagai tanggal / waktu setempat. 2) Ya, Anda harus menggunakan Math.floor(this.getTime() / 1000)dalam hal ini.
DCoder
Menjawab di sini karena saya perlu memperbarui kode ... Ini untuk memiliki cap waktu Unix di UTC untuk tanggal yang ada : function () {return Math.floor (Tanggal baru (this.getUTCFullYear (), this.getUTCMonth (), this.getUTCDate (), this.getUTCHours (), this.getUTCMinutes (), this.getUTCSeconds ()) .getTime () / 1000); } Ini berarti saya dapat melakukan: var n = Tanggal baru (2008,10,10) ... ... n.getUTCTime (); (Ini akan BERBEDA dengan n.getUTCTime ())
Merc
1
Terima kasih, Bro File kerjanya Math.floor ((Tanggal baru ()). GetTime () / 1000)
Manoj Patel
51

Anda juga bisa melakukannya dengan menggunakan getTimezoneOffset dan getTime,

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

console.log("UTCseconds", UTCseconds)

Shiplu Mokaddim
sumber
4
Terima kasih, ini tidak dapat ditemukan di internet!
Theofanis Pantelides
Saya menguji kode berikut: var tt = new Date('Thu Jan 01 1970 08:00:00 GMT+0800 (China Standard Time)'); (tt.getTime() - tt.getTimezoneOffset()*60*1000)/1000. Tampaknya tt.getTime() - tt.getTimezoneOffset()benar untuk GMT+0800.
zangw
1
Ini lebih baikvar UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60)
StefansArya
Sepertinya ini tidak berfungsi seperti yang tertulis .. Sepertinya Anda harus memasukkan string waktu ke dalam new Date()yang mencakup zona waktu .. yang agak mengalahkan tujuan mencoba melakukannya dalam js ..
claudekennilol
Ini benar-benar salah, nilai yang diberikan ke UTCseconds bukan UTC detik. Nilai waktu Date adalah UTC, mengubahnya dengan metode apa pun yang berarti ia mewakili momen yang berbeda dalam waktu.
RobG
35

Cara termudah untuk mendapatkan waktu UTC dalam format konvensional adalah sebagai berikut:

new Date().toISOString()
"2016-06-03T23:15:33.008Z"
Tahsin Turkoz
sumber
3
Ini jawaban yang benar. Banyak jawaban lain memberikan "string waktu universal" tetapi tidak memberikan "waktu universal terkoordinasi" saat ini. Saya tidak mengerti mengapa semuanya begitu rumit di sini.
gburton
@Gburton terima kasih. Hargailah Anda melihat cara sederhana menuju kebenaran. :)
Tahsin Turkoz
1
Saya menggunakan ini, bersama dengan ".split ('T') [0]" untuk perbandingan berbasis tanggal YYYY-MM-DD yang mudah.
Sean O
Senang memiliki @SeanO
Tahsin Turkoz
Ini memberikan string waktu UTC, tetapi OP meminta cap waktu UTC (zaman)
Jordi Nebot
13

Saya benar-benar berpikir nilai Date dalam js jauh lebih baik daripada mengatakan objek C # DateTime. Objek C # DateTime memiliki properti Jenis, tetapi tidak ada zona waktu mendasar yang ketat seperti itu, dan konversi zona waktu sulit dilacak jika Anda mengonversi antara dua waktu non UTC dan non lokal. Di js, semua nilai Tanggal memiliki nilai UTC dasar yang diedarkan dan diketahui terlepas dari konversi zona waktu atau yang Anda lakukan. Keluhan terbesar saya tentang objek Date adalah jumlah perilaku tidak terdefinisi yang telah dipilih oleh pelaksana browser, yang dapat membingungkan orang yang menyerang tanggal di js dengan trial and error daripada membaca spec. Menggunakan sesuatu seperti iso8601.js memecahkan perilaku yang bervariasi ini dengan mendefinisikan satu implementasi objek Date.

Secara default, spesifikasi mengatakan Anda dapat membuat tanggal dengan format tanggal ISO 8601 yang diperpanjang seperti

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

Jadi Anda dapat menyimpulkan waktu UTC yang tepat dengan cara ini.

Ketika Anda ingin meneruskan nilai Tanggal kembali ke server yang akan Anda hubungi

someDate.toISOString();

atau jika Anda lebih suka bekerja dengan cap waktu milidetik (jumlah milidetik dari 1 Januari 1970 UTC)

someDate.getTime();

ISO 8601 adalah standar. Anda tidak dapat bingung tentang apa arti string tanggal jika Anda menyertakan offset tanggal. Apa artinya ini bagi Anda sebagai pengembang adalah Anda tidak perlu berurusan dengan konversi waktu setempat sendiri . Nilai waktu lokal ada murni untuk kepentingan pengguna, dan nilai tanggal secara default ditampilkan di waktu lokal mereka. Semua manipulasi waktu lokal memungkinkan Anda untuk menampilkan sesuatu yang masuk akal bagi pengguna dan untuk mengubah string dari input pengguna. Ini praktik yang baik untuk mengonversi ke UTC sesegera mungkin, dan objek js Date menjadikan ini cukup sepele.

Pada sisi negatifnya tidak ada banyak ruang untuk memaksa zona waktu atau lokal untuk klien (yang saya tahu), yang dapat mengganggu pengaturan spesifik situs web, tapi saya kira alasan di balik ini adalah bahwa itu adalah pengguna konfigurasi yang tidak boleh disentuh.

Jadi, singkatnya, alasan tidak ada banyak dukungan asli untuk manipulasi zona waktu adalah karena Anda tidak ingin melakukannya.

Matt Esch
sumber
12

Anda biasanya tidak perlu melakukan banyak "manipulasi zona waktu" di sisi klien. Sebagai aturan saya mencoba untuk menyimpan dan bekerja dengan tanggal UTC, dalam bentuk ticksatau " jumlah milidetik sejak tengah malam 1 Januari 1970. " Ini benar-benar menyederhanakan penyimpanan, penyortiran, perhitungan offset, dan yang paling penting, membuat Anda sakit kepala dari penyesuaian "Waktu Penghematan Siang Hari". Inilah sedikit kode JavaScript yang saya gunakan.

Untuk mendapatkan waktu UTC saat ini:

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;
}

Maka yang biasanya Anda perlukan adalah memformat tanggal / waktu untuk pengguna akhir untuk zona waktu dan format lokal mereka . Yang berikut menangani semua kerumitan format tanggal dan waktu pada komputer klien:

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();
}

Jadi contoh berikut:

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>");

Mengembalikan yang berikut (untuk lokal Bahasa Inggris AS saya):

ticks = 1409103400661, DateTime = 8/26/2014 6:36:40 PM, Tanggal = 8/26/2014, Waktu = 6: 36: 40 PM

ahmd0
sumber
1
Dengan menambahkan getTimezoneOffsetnilai dalam getCurrentTimeUTCfungsi Anda, Anda sebenarnya mengembalikan waktu yang berbeda. Hasil getTimeini sudah di UTC.
Matt Johnson-Pint
1
@MattJohnson: Itu tidak benar. Hasilnya tmLoc.getTime()adalah offset terhadap waktu setempat. Itu mudah untuk memeriksa apakah Anda memiliki akses ke apa pun yang menjalankan JavaScript.
ahmd0
2
Maaf, tapi itu tidak benar. Lihat referensi MDN . Anda juga dapat melihat ini di spec ECMAScript. §15.9.3.3 menjelaskangetTime , yang menunjukkan Anda pada "nilai waktu" yang ditentukan dalam §15.9.5 , yang merupakan PrimitiveValue, sebagaimana diatur dalam §15.9.3.3 secara eksplisit sebagai UTC.
Matt Johnson-Pint
2
Nah, karena Anda memperoleh tmLocvia new Date(), maka itu hal yang sama. Zona waktu akan memengaruhi output string tmLoc.toString()dan item serupa, tetapi tidak akan memengaruhi. tmLoc.getTime() Itu selalu hanya beberapa milidetik sejak tengah malam 1970-01-01 di UTC.
Matt Johnson-Pint
1
@StefansArya://The offset is in minutes -- convert it to ms
ahmd0
5

Saya pikir ini adalah solusi yang lebih baik

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

// UTC seconds
new Date(Date.now()+(new Date().getTimezoneOffset()*60000)).getTime()/1000|0
koalex
sumber
Jawaban lain yang salah, getTime mengembalikan offset UTC, menambahkan offset zona waktu lokal sepenuhnya mengacaukannya. Offset ECMAScript adalah + ve untuk barat dan -ve untuk timur, sehingga mereka harus dikurangi dari UTC untuk mendapatkan lokal. Tetapi karena nilai waktu adalah UTC untuk memulai, menambahkannya pada dasarnya menggesernya dari UTC ke arah yang berlawanan dengan offset lokal.
RobG
4

Jika Anda menginginkan satu liner , Timestamp UTC Unix dapat dibuat dalam JavaScript sebagai:

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

Ini akan memperhitungkan zona waktu sistem. Pada dasarnya waktu berlalu dalam Detik sejak zaman.

Bagaimana itu bekerja:

  • Membuat objek date: new Date().
  • Konversikan ke stempel waktu dengan menambahkan unary +sebelum pembuatan objek untuk mengubahnya timestamp integer. : +new Date().
  • Konversi milidetik ke detik: +new Date() / 1000
  • Gunakan double tildes untuk melengkapi nilai menjadi integer. :~~(+new Date())
Kushal Likhi
sumber
7
itu tilde, bukan tilda(sic). Sayangnya itu tidak akan membiarkan saya menghapus kesalahan ketik, saya harus melakukan setidaknya 6 pengeditan karakter. Smooth, Stackexchange, smooth
Fred
3
Jangan gunakan ini . Dengan spec ecma saat ini, operasi bitwise (seperti tilde - bitwise tidak) menangani nilai integer yang ditandatangani sebesar 32 bit. Itu berarti sihir tilde ini tidak akan berfungsi setelah 19 Januari 2038 ketika nilai timestamp akan melebihi nilai maks integer bertanda 32 bit. jsfiddle.net/phb20ymb
Sharky
3

Saya ingin memperjelas bahwa Date baru (). GetTime () sebenarnya mengembalikan nilai UTC, jadi ini adalah cara yang sangat membantu untuk menyimpan dan mengelola tanggal dengan cara yang agnostik terhadap waktu yang dilokalkan.

Dengan kata lain, jangan repot-repot dengan semua fungsi javascript UTC. Sebagai gantinya, cukup gunakan Date.getTime ().

Info lebih lanjut tentang penjelasannya ada di sini: Jika javascript "(Tanggal baru ()). GetTime ()" dijalankan dari 2 Zona Waktu yang berbeda.

Stan Lin
sumber
3

Saya menggunakan yang berikut ini:

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

Setelah mendefinisikan metode ini, Anda dapat melakukan:

var utcTime = new Date().getUTCTime();
jlbofh
sumber
Solusi terbersih. TERIMA KASIH!
avalanche1
Tapi itu bukan solusi bersih untuk mengirim tanggal, karena TimeStamps selalu UTC. Solusi terbaik bagi saya ketika mengirim tanggal, adalah dengan menggunakan representasi string seperti "dd / MM / yyyy HH: mm: ss" dan kemudian menguraikannya di sisi server dengan TimeZone default server untuk mendapatkan timestamp UTC atau apa pun. Lihat jawaban
jlbofh
2
parsing sebuah string - Anda menyebutnya bersih? meh
avalanche1
Pastikan, ada metode untuk menghasilkan tanggal dalam format string sesuai dengan spesifikasi ISO. Metode ini adalah toISOString (). Anda dapat menguraikannya dengan bersih di Jawa menggunakan sesuatu seperti:DateTime dt = new DateTime ("2018-07-15T02:36:00+02:00");
jlbofh
Jawaban lain yang salah, this.getTime()mengembalikan offset UTC, mengurangi offset zona waktu lokal menjadikannya lokal, bukan UTC jadi dapatkanUTCTime mengembalikan offset lokal, bukan UTC.
RobG
2

Saya kagum dengan betapa kompleksnya pertanyaan ini.

Ini semua identik, dan nilai integernya semuanya === EPOCH time: D

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

Jangan percaya padaku, checkout: http://www.epochconverter.com/

fliptopbox
sumber
2

Karena new Date().toUTCString()mengembalikan string seperti "Wed, 11 Oct 2017 09:24:41 GMT"Anda dapat mengiris 3 karakter terakhir dan meneruskan string yang diiris ke 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)
Maurice Wipf
sumber
1

Sunting: Kode di bawah ini TIDAK berfungsi. Saya selalu berasumsi bahwa Date baru (). GetTime () mengembalikan jumlah detik sejak tanggal 1 Januari 1970 DALAM TIMEZONE SAAT INI. Ini tidak terjadi: getTime () mengembalikan jumlah detik dalam UTC. Jadi, kode di bawah ini tidak terlalu banyak penyesuaian. Terima kasih semuanya!]

Pertama-tama, terima kasih atas wawasan fantastis Anda. Saya kira pertanyaan saya memiliki judul yang salah ... seharusnya "Dapatkan Timestamp UTC Unix untuk tanggal yang ada".

Jadi, jika saya memiliki objek kencan:

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

Saya mengejar fungsi yang akan memberi tahu saya "The UTC Unix Timestamp".

Fungsi ini tampaknya merupakan trik nyata:

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

Perhatikan bahwa ini berfungsi pada "ini" Ini berarti saya dapat melakukan:

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

n.getUTCUnixTime();

Dan dapatkan jumlah detik sejak 1 Januari 1970 dalam waktu Unix. Baik?

Agak gila, bagi saya, Javascript menyimpan segala sesuatu dalam waktu UTC, tapi kemudian untuk mendapatkan nomor itu saya harus membuat objek Date baru melewati masing-masing getter UTC dan akhirnya memanggil getTime () untuk itu ...

Merc.

Merc
sumber
1
apakah Anda melihat pembaruan @ DCoder untuk jawabannya? Metode Anda getUTCUnixTimemendapatkan waktu yang salah, dan JavaScript memang menyediakan cara mudah untuk mendapatkan cap waktu unix dari Dateobjek - menggunakan getTimemetode ini. Lihat semua jawaban lain.
Anurag
1
Ugh kamu benar, lihat saja mereka. (Membenturkan kepala ke dinding)
Merc
1

Saya pikir ini yang Anda harapkan ...

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

Sekarang,

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

Setelah kamu melakukan ini

new Date(dateString).getTime() / 1000

Sudah cap waktu UTC

   const getUnixTimeUtc = (dateString = new Date()) => Math.round(new Date(dateString).getTime() / 1000)

Saya menguji di https://www.unixtimestamp.com/index.php

kusut
sumber
0

Menggunakan day.js

Di browser:

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>

Di node.js:

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

Anda mendapatkan cap waktu unix UTC tanpa milidetik.

Ilyich
sumber
-2

Ini akan mengembalikan stempel waktu dalam UTC:

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

Yash Pandya
sumber
2
Ini tidak mengembalikan waktu di UTC: new Date(new Date().toUTCString())berikan Rabu 04 Oktober 2017 07:20:14 GMT + 0200 (GMT + 02:00)
Bas van Dijk