JavaScript'te UTC Zaman Damgası'nı nasıl edinebilirim?


159

Bir web uygulaması yazarken, DB'de tüm zaman zamanlarını UTC zaman damgaları olarak saklamak mantıklıdır .

JavaScript'te Timezone manipülasyonu konusunda yerel olarak çok fazla şey yapamayacağınızı fark ettiğimde şaşırdım.

Date nesnesini biraz genişlettim. Bu işlev mantıklı mı? Temel olarak, sunucuya her şey gönderdiğimde, bu işlevle biçimlendirilmiş bir zaman damgası olacak ...

Burada büyük sorunlar görebiliyor musunuz? Ya da belki farklı bir açıdan bir çözüm?

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

Bana biraz kıvrık geliyor. Performanstan da o kadar emin değilim.


Bunun eski bir soru olduğunu biliyorum, ancak Date nesnesi gibi yerel nesneleri genişletmemeye çalışın. Sorunun kendisinden hoşlandığım için kaldırıldı.
trysis

Date.parse (yeni Tarih (). ToUTCString ())
Sagi

26
Bu, bugün beslememde ortaya çıkan eski bir soru ve yanlış bilgilerle dolu. Zaman damgası her zaman UTC'dir. new Date().toString()size geçerli saat dilimi Zamanın gösterildiği gösterecektir, new Date().toUTCString()size UTC zamanı repr gösterecektir, ancak new Date().getTime()olduğu zaman UTC "(aynı zamanda POSIX zaman veya dönem süresine olarak da bilinir) Unix zaman anlarının tarif eden bir sistemdir: Unix zaman olarak tanımlanır ne olduğundan, zaman içinde, 00:00:00 tarihinden bu yana geçen saniye sayısı olarak tanımlanır. Eşgüdümlü Evrensel Saat (UTC), 1 Ocak 1970 Perşembe, artık saniye saymıyor. "
Amadan

Yanıtlar:


155
  1. Bu şekilde yapılan tarihler, yerel saat dilimini kullanır ve bu da oluşturulan tarihi yanlış yapar. Belirli bir tarih nesnesinin saat dilimini ayarlamak, nesneyi saat dilimini içeren bir tarih dizesinden oluşturmaktır. (Bunu daha eski bir Android tarayıcısında çalıştırırken sorun yaşadım.)

  2. getTime()Düz saniye değil milisaniye döndürdüğünü unutmayın .

Bir UTC / Unix zaman damgası için aşağıdakiler yeterli olmalıdır:

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

Sonuçta geçerli saat dilimi sapmasını hesaba katacaktır. Dize temsili için David Ellis'in cevabı işe yarıyor.

Netleştirmek için:

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

Bu girdi yerel saat olarak kabul edilir . Eğer UTC zamanı geçirilen, sonuçları farklı olacaktır. Gözlemle (Şu anda GMT +02: 00'deyim ve 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

Ayrıca getUTCDate()bunun yerine kullanılamayacağını unutmayın getUTCDay(). Çünkü ayın gününügetUTCDate() döndürür ; oysa haftanın gününü döndürür .getUTCDay()


1
1) Bir randevum inşa etmedi ... Ben üzerinde çalıştığı bir prototip işlevini eklendi bu . 2) İyi bir nokta, Math.floor / 1000 yapmalıyım - ama yine de mevcut bir tarih nesnesinin UTC zaman damgasına sahip olmak için bu işleve ihtiyacım olacaktı ... değil mi?
Merc

@Merc: 1) Aradığınız, new Date()UTC girişinizden yeni bir tarih oluşturur, ancak yerel tarih / saat olarak kabul eder. 2) Evet, Math.floor(this.getTime() / 1000)bu durumda kullanmalısınız .
DCoder

Burada kodu güncellemek gerekiyor gibi cevap ... Bu, mevcut bir tarih için UTC Unix zaman damgası olması için : function () {return Math.floor (yeni Tarih (this.getUTCFullYear (), this.getUTCMonth (), this.getUTCDate (), this.getUTCHours (), this.getUTCMinutes (), this.getUTCSeconds ()) .getTime () / 1000); } Bu, yapabileceğim anlamına gelir: var n = new Date (2008,10,10) ... ... n.getUTCTime (); (Bu, n.getUTCTime () işlevinden FARKLI olacaktır)
Merc

1
Thanks Bro Onun çalışma dosyası Math.floor ((yeni Tarih ()). GetTime () / 1000)
Manoj Patel

51

Bunu getTimezoneOffset ve getTime kullanarak da yapabilirsiniz,

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

console.log("UTCseconds", UTCseconds)


4
Teşekkürler, bu internette bulunacak hiçbir yer yok!
Theofanis Pantelides

Aşağıdaki kodları test etmek: var tt = new Date('Thu Jan 01 1970 08:00:00 GMT+0800 (China Standard Time)'); (tt.getTime() - tt.getTimezoneOffset()*60*1000)/1000. İçin tt.getTime() - tt.getTimezoneOffset()doğru gibi görünüyor GMT+0800.
zangw

1
Bu daha iyivar UTCseconds = (Math.floor(x.getTime()/1000) + x.getTimezoneOffset()*60)
StefansArya

Bu yazılı olarak çalışmıyor gibi görünüyor .. new Date()Bir zaman dilimi içeren içine zaman dizesi geçmek zorunda gibi görünüyor ... hangi tür js yapmaya çalışmanın amacını yener ..
claudekennilol

Bu atanan değer, sadece yanlış UTCseconds değil UTC saniye .. bir randevu zaman değeridir olduğu zaman farklı bir anını temsil herhangi bir yöntemi vasıtası ile değiştirmeyi, UTC.
RobG

35

UTC saatini geleneksel biçimde almanın en kolay yolu aşağıdaki gibidir:

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

3
Bu doğru cevap. Diğer cevapların birçoğu "evrensel zaman dizgisi" verir, ancak geçerli "evrensel koordineli zamanı" vermez. Burada her şeyin neden bu kadar karmaşık olduğunu anlamıyorum.
gburton

Teşekkürler @gburton. Hakikatin basit yolunu gördüğünüz için teşekkür ederiz. :)
Tahsin Turkoz

1
Bunu, kolay YYYY-AA-GG tarih tabanlı karşılaştırmalar için ".split ('T') [0]" ile birlikte kullanıyorum.
Sean O

@SeanO
Tahsin Turkoz

Bu bir UTC zaman dizesi sağlar, ancak OP bir UTC zaman damgası (çağ) ister
Jordi Nebot

13

Aslında js Tarih değerleri C # DateTime nesneleri söylemek çok daha iyi olduğunu düşünüyorum. C # DateTime nesnelerinin bir Kind özelliği vardır, ancak altta yatan kesin bir saat dilimi yoktur ve iki UTC olmayan ve yerel olmayan saat arasında dönüştürme yapıyorsanız saat dilimi dönüşümlerini izlemek zordur. Js'de, tüm Date değerleri, yaptığınız en uzak veya saat dilimi dönüşümlerinden bağımsız olarak aktarılan ve bilinen temel bir UTC değerine sahiptir. Date nesnesi ile ilgili en büyük şikayetim, tarayıcı uygulayıcılarının dahil etmeyi seçtiği tanımlanmamış davranış miktarıdır; İso8601.js gibi bir şey kullanmak, Date nesnesinin tek bir uygulamasını tanımlayarak bu değişken davranışı çözer.

Varsayılan olarak teknik özellik, genişletilmiş ISO 8601 tarih biçimiyle tarihler oluşturabileceğinizi söylüyor

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

Böylece tam UTC saatini bu şekilde çıkarabilirsiniz.

Tarih değerini sunucuya geri aktarmak istediğinizde,

someDate.toISOString();

veya milisaniye zaman damgası ile çalışmayı tercih ediyorsanız (1 Ocak 1970 UTC'den milisaniye sayısı)

someDate.getTime();

ISO 8601 bir standarttır. Tarih ofsetini eklerseniz, bir tarih dizesinin ne anlama geldiği konusunda kafanız karışamaz. Bir geliştirici olarak bunun sizin için anlamı , yerel zaman dönüşümleriyle asla başa çıkmak zorunda kalmamanızdır . Yerel saat değerleri yalnızca kullanıcının yararına mevcuttur ve tarih değerleri varsayılan olarak yerel saatlerinde görüntülenir. Tüm yerel saat manipülasyonları, kullanıcıya duyarlı bir şey görüntülemenize ve dizeleri kullanıcı girişinden dönüştürmenize izin verir. En kısa zamanda UTC'ye dönüştürmek iyi bir uygulamadır ve js Date nesnesi bunu oldukça önemsiz hale getirir.

Dezavantajı, web sitesine özgü ayarlar için can sıkıcı olabilen istemci (zamanın farkında olduğum) için zaman dilimini veya yerel ayarı zorlamak için çok fazla bir kapsam yoktur, ancak bunun arkasındaki mantık bunun bir kullanıcı olmasıdır. dokunulmaması gereken yapılandırma.

Kısacası, saat dilimi manipülasyonu için çok fazla yerel desteğin olmamasının nedeni, bunu yapmak istemezsiniz.


12

Genellikle istemci tarafında çok fazla "Saat Dilimi manipülasyonu" yapmanız gerekmez. Kural olarak UTC tarihlerini, ticks" 1 Ocak 1970 gece yarısından bu yana geçen milisaniye sayısı " biçiminde depolamaya ve çalışmaya çalışıyorum . Bu, ofsetlerin depolanmasını, sıralanmasını, hesaplanmasını gerçekten kolaylaştırır ve en önemlisi, "Yaz Saati Uygulaması" ayarlarının baş ağrısını ortadan kaldırır. İşte kullandığım küçük bir JavaScript kodu.

Geçerli UTC saatini almak için:

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

Genel olarak ihtiyacınız olan şey, son kullanıcının yerel saat dilimi ve biçimi için tarih / saati biçimlendirmektir. Aşağıdakiler, istemci bilgisayardaki tarih ve saat biçimlerinin tüm karmaşıklıklarına dikkat eder:

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

Yani aşağıdaki örnek:

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

Aşağıdakileri döndürür (ABD İngilizcesi yerel ayarım için):

keneler = 1409103400661, DateTime = 8/26/2014 18:36:40, Tarih = 8/26/2014, Zaman = 6: 36: 40 PM


1
İşlevinize getTimezoneOffsetdeğer ekleyerek, getCurrentTimeUTCaslında zaman içinde farklı bir nokta döndürürsünüz. Sonucu getTimeolduğu zaten UTC.
Matt Johnson-Pint

1
@ MattJohnson: Bu yanlış. Sonucu tmLoc.getTime()yerel saatle mahsup bir olduğunu. JavaScript çalıştıran herhangi bir şeye erişiminizin olup olmadığını kontrol etmek kolaydır.
ahmd0

2
Üzgünüm, ama bu doğru değil. MDN referansına bakın . Bunu ECMAScript spesifikasyonunda da görebilirsiniz. §15.9.3.3 açıklanırgetTime tanımlanan "zaman değerine" sizi işaret hangi §15.9.5 bir olduğunu, PrimitiveValueiçinde set olarak, §15.9.3.3 açıkça UTC olarak.
Matt Johnson-Pint

2
Eh, tmLocüzerinden elde ettiğiniz için new Date(), o zaman aynı şey. Saat dilimi tmLoc.toString()ve benzer öğelerin dize çıktısını etkiler , ancak etkilemez tmLoc.getTime() Bu, UTC'de 1970-01-01 gece yarısından bu yana her zaman yalnızca milisaniye sayısıdır.
Matt Johnson-Pint

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

5

Bence bu daha iyi bir çözüm

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

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

Başka bir yanlış yanıt olan getTime , UTC saatini döndürür ve yerel saat dilimi ofsetini tamamen bozar. ECMAScript ofsetleri batı için + ve doğu için -ve'dir, bu nedenle yerel almak için UTC'den çıkarılmalıdır. Ancak, zaman değeri başlangıç ​​için UTC olduğundan, eklenmesi esas olarak UTC'den yerel yöne ters yönde kaydırır.
RobG

4

Bir astar istiyorsanız , UTC Unix Zaman Damgası JavaScript'te şu şekilde oluşturulabilir:

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

Bu, sistemin saat dilimini dikkate alacaktır. Temelde dönemden bu yana Saniye cinsinden geçen süre.

Nasıl çalışır:

  • Tarih nesnesi oluştur: new Date() .
  • Dönüştürmek için unary +nesne oluşturmadan önce ekleyerek zaman damgasına dönüştürün timestamp integer. :+new Date() .
  • Milisaniyeyi saniyeye çevir: +new Date() / 1000
  • Değeri tamsayıya yuvarlamak için çift ​​tild kullanın . :~~(+new Date())

7
öyle tildedeğil tilda. Ne yazık ki bir yazım hatasını kaldırmama izin vermiyor, en az 6 karakter düzenlemesi yapmam gerekiyor. Pürüzsüz, Stackexchange, pürüzsüz
Fred

3
Bunu kullanmayın . Mevcut ecma özelliği ile, bitsel işlemler (tilde - bitsel değil gibi) 32 bitlik işaretli tam sayı değerlerini işler. Bu, tilde sihrinin, zaman damgası değerinin 32 bit işaretli tam sayının maksimum değerinin üzerinde olacağı 19 Ocak 2038'den sonra çalışmayacağı anlamına gelir . jsfiddle.net/phb20ymb
Sharky

3

Yeni Date (). GetTime () aslında bir UTC değeri döndürüyor açıkça belirtmek istiyorum, bu yüzden tarihler yerelleştirilmiş saatlere agnostik bir şekilde depolamak ve yönetmek için gerçekten yararlı bir yoludur.

Başka bir deyişle, tüm UTC javascript işlevleriyle uğraşmayın. Bunun yerine Date.getTime () kullanın.

Açıklama hakkında daha fazla bilgi burada: javascript "(new Date ()). GetTime ()" 2 farklı Timezondan çalıştırılırsa.


3

Aşağıdakileri kullanıyorum:

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

Bu yöntemi tanımladıktan sonra şunları yapabilirsiniz:

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

En temiz çözüm. TEŞEKKÜRLER!
avalanche1

Ancak bu, tarihleri ​​göndermek için temiz bir çözüm değildir, çünkü TimeStamp'lar her zaman UTC'dir. Tarih gönderirken benim için en iyi çözüm, "dd / AA / yyyy SS: dd: ss" gibi bir dize temsili kullanmak ve sonra bir UTC zaman damgası veya herhangi bir şey almak için sunucunun varsayılan TimeZone'u ile sunucu tarafında ayrıştırmaktır. Bu yanıtı
jlbofh

2
bir dizeyi ayrıştırma - buna temiz mi diyorsun? meh
avalanche1

ISO özelliklerine göre dize biçiminde bir tarih oluşturma yöntemleri olduğundan emin olun. Yöntem toISOString () yöntemidir. Java'da temiz bir şekilde aşağıdakileri kullanarak ayrıştırabilirsiniz:DateTime dt = new DateTime ("2018-07-15T02:36:00+02:00");
jlbofh

Başka bir yanlış yanıt, this.getTime()bir UTC uzaklığı döndürür, yerel saat dilimi uzaklığını çıkarmak yerel değil yerel kılar, getUTCTime UTC'yi değil yerel bir uzaklığı döndürür.
RobG

2

Bu sorunun ne kadar karmaşık hale geldiğine şaşırdım.

Bunların hepsi aynıdır ve tamsayı değerlerinin tümü === EPOCH zamanı: D

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

Bana inanma, ödeme: http://www.epochconverter.com/


2

Yana new Date().toUTCString()iadeler benzeri bir dize "Wed, 11 Oct 2017 09:24:41 GMT"size son 3 karakterden dilim ve dilimlenmiş dize için iletebilirsiniz 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: Aşağıdaki kod çalışmıyor. Her zaman yeni Date (). GetTime () 'nin 1 Ocak 1970'den beri AKIM ZAMANINDA saniye sayısını döndürdüğünü varsayıyordum. Durum böyle değildir: getTime (), UTC cinsinden saniye sayısını döndürür. Bu nedenle, aşağıdaki kod brüt aşırı ayarlama yapar. Herkese teşekkürler!]

Her şeyden önce, harika fikirleriniz için teşekkür ederim. Sanırım sorum yanlış başlık vardı ... "Mevcut bir tarih için UTC Unix Zaman Damgası alın" olmalıdır.

Yani, bir tarih nesnesi varsa:

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

"UTC Unix Zaman Damgası" nı söyleyen bir işlev peşindeydim.

Bu işlev gerçek hile gibi görünüyor:

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

"Bu" üzerinde çalıştığına dikkat edin Bu, yapabileceğim anlamına gelir:

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

n.getUTCUnixTime();

Ve 1 Ocak 1970'den bu yana Unix zamanında saniye sayısını alın. Sağ?

Bana göre, Javascript her şeyi UTC saatlerinde saklıyor, ama sonra bu sayıyı elde etmek için tek tek UTC alıcılarını geçen yeni bir Date nesnesi oluşturmak ve sonunda bunun için getTime () çağırmak zorunda ...

Merc.


1
DCoder'ın cevabındaki güncellemesini gördün mü? Kişisel yöntem getUTCUnixTimeyanlış zamanda alır ve JavaScript yapar bir gelen unix zaman damgası almak için basit bir yol sağlar Datenesne - kullanılarak getTimeyöntemi. Diğer tüm cevapları görün.
Anurag

1
Ugh haklısın, sadece gördüm. (Kafayı duvara vurarak)
Merc

1

Bence bu beklediğiniz şey ...

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

Şimdi,

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


0

Day.js kullanma

Tarayıcıda:

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>

Node.js'de:

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

Milisaniye olmadan bir UTC unix zaman damgası alırsınız.


-2

Bu, UTC'de zaman damgasını döndürür:

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


2
Bu UTC zamanı dönmez: new Date(new Date().toUTCString()): Çar Ekm 04 2017 07:20:14 GMT + 0200 (00 GMT + 02) verir
Bas van Dijk
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.