JavaScript'te ISO 8601 biçimli bir dizeyi nasıl çıkarırım?


247

Bir Datenesnem var. Aşağıdaki kod parçasının bir kısmını nasıl oluşturabilirim title?

<abbr title="2010-04-02T14:12:07">A couple days ago</abbr>

Başka bir kütüphaneden "kelimelerle göreli zaman" kısmı var.

Aşağıdakileri denedim:

function isoDate(msSinceEpoch) {

   var d = new Date(msSinceEpoch);
   return d.getUTCFullYear() + '-' + (d.getUTCMonth() + 1) + '-' + d.getUTCDate() + 'T' +
          d.getUTCHours() + ':' + d.getUTCMinutes() + ':' + d.getUTCSeconds();

}

Ama bu bana şunu veriyor:

"2010-4-2T3:19"

Yanıtlar:


453

Zaten bir fonksiyon var toISOString():

var date = new Date();
date.toISOString(); //"2011-12-19T15:28:46.493Z"

Bir şekilde, onu desteklemeyen bir tarayıcıdaysanız , sizi ele geçiririm:

if ( !Date.prototype.toISOString ) {
  ( function() {

    function pad(number) {
      var r = String(number);
      if ( r.length === 1 ) {
        r = '0' + r;
      }
      return r;
    }

    Date.prototype.toISOString = function() {
      return this.getUTCFullYear()
        + '-' + pad( this.getUTCMonth() + 1 )
        + '-' + pad( this.getUTCDate() )
        + 'T' + pad( this.getUTCHours() )
        + ':' + pad( this.getUTCMinutes() )
        + ':' + pad( this.getUTCSeconds() )
        + '.' + String( (this.getUTCMilliseconds()/1000).toFixed(3) ).slice( 2, 5 )
        + 'Z';
    };

  }() );
}

1
.toISOString () kesinlikle tarih UTC olarak döndürür?
Jon Wells

new Date("xx").toISOString()üretir NaN-NaN-NaNTNaN:NaN:NaN.NZYerel uygulama RangeException atar.
Joseph Lennox

Bir tarih nesnesini bir sabun servisine geçirmek istiyorsanız ... işte bu! :) Teşekkürler.
thinklinux

1
OP tarafından sağlanan örnekte milisaniye veya zaman dilimi yoktur.
Dan Dascalescu

"GetUTCFullYear" gibi tüm bu işlev çağrıları, IE belge modu 5 tarafından bilinmediği için başarısız oluyor.
Elaskanator

63

Https://developer.mozilla.org/tr/Core_JavaScript_1.5_Reference:Global_Objects:Date sayfasındaki son örneğe bakın :

/* Use a function for the exact format desired... */
function ISODateString(d) {
    function pad(n) {return n<10 ? '0'+n : n}
    return d.getUTCFullYear()+'-'
         + pad(d.getUTCMonth()+1)+'-'
         + pad(d.getUTCDate())+'T'
         + pad(d.getUTCHours())+':'
         + pad(d.getUTCMinutes())+':'
         + pad(d.getUTCSeconds())+'Z'
}

var d = new Date();
console.log(ISODateString(d)); // Prints something like 2009-09-28T19:03:12Z

1
OP ( <abbr title="2010-04-02T14:12:07">) tarafından sağlanan örnekte saat dilimi yoktur. Belki de bir UI zaman dizesi için anlamlı olan yerel saati istediler?
Dan Dascalescu

60

Web'deki hemen hemen her ISO-metodu, dizeyi çıkarmadan önce "Z" ulu zamanına (UTC) dönüştürerek uygulayarak saat dilimi bilgilerini düşürür. Tarayıcının yerel .toISOString () yöntemi de saat dilimi bilgilerini düşürür.

Bu, sunucu veya alıcı, gönderenin saat dilimi bilgilerini alırken, tam bir ISO tarihini her zaman Zulu saatine veya hangi saat dilimine ihtiyaç duyarsa değiştirebilir.

Karşılaştığım en iyi çözüm Moment.js javascript kütüphanesini kullanmak ve aşağıdaki kodu kullanmaktır:

Geçerli ISO saatini saat dilimi bilgileri ve milisaniye ile almak için

now = moment().format("YYYY-MM-DDTHH:mm:ss.SSSZZ")
// "2013-03-08T20:11:11.234+0100"

now = moment().utc().format("YYYY-MM-DDTHH:mm:ss.SSSZZ")
// "2013-03-08T19:11:11.234+0000"

now = moment().utc().format("YYYY-MM-DDTHH:mm:ss") + "Z"
// "2013-03-08T19:11:11Z" <- better use the native .toISOString() 

Yerel bir JavaScript Tarih nesnesinin ISO saatini saat dilimi bilgisiyle, ancak milisaniye olmadan almak için

var current_time = Date.now();
moment(current_time).format("YYYY-MM-DDTHH:mm:ssZZ")

Bu, Date.today () gibi işlevleri elde etmek için Date.js ile birleştirilebilir.

Böyle biçimlendirilmiş bir tarih dizesi JSON derleyicisidir ve bir veritabanında depolanmak için iyi bir şekilde ödünç verilir. Python ve C # hoşuna gidiyor.


21
tarihleri ​​insanlarla şeyler dont. Sadece moment.js kullanın ve saçınızı kurtarın.
Valamas

1
aslında, python ve db'lerde bir acı olduğu ortaya çıktı. db'nin UTC kullanımı (prob yok, kolayca UTC sunucu tarafına dönüştürebileceğiniz için), bu nedenle ofset bilgilerini tutmak istiyorsanız başka bir alana ihtiyacınız vardır. Python, javascript'in milisaniye yerine nanosaniye kullanımını tercih eder, bu da genellikle düz saniye boyunca genellikle yeterli ve tercih edilir. Python'da yalnızca dateutil.parser.parse doğru şekilde ayrıştırır ve milisaniye ISO'su yazmak için bir "_when = when.strftime ("% Y-% m-% dT% H:% M:% S.% f% z "); nanos'u milis'e dönüştürmek için _when [: - 8] + _when [-5:]" döndür. bu hoş değil.
Daniel F

3
Aslında sadece bu yüzden gibi biçimini atlayabilirsiniz: moment(new Date()).format(). Msgstr YYYY-MM-DDTHH:mm:ssZ" Sürüm 1.5.0'dan itibaren, format olmadan anı # biçimini çağırmak varsayılan olarak ... ISO8601 biçimini alacaktır ". Doktor: momentjs.com/docs/#/displaying/fromnow adresinden
user193130

1
@191930 @ iyi nokta ama çıkış yerel yöntemden farklı olduğu için gerçekten dikkatli olmanız gerekir. moment().format() "2015-03-04T17:16:05+03:00" (new Date()).toISOString() "2015-03-04T14:16:24.555Z"
Olga

1
Belki seçici olmakla birlikte, bu örnekler saat dilimini değil, UTC den geçerli ofseti döndürür. Bir saat dilimi, örneğin "Amerika / Toronto" olarak ifade edilen coğrafi bir bölgedir. Birçok saat dilimi UTC dengelerini yılda iki kez değiştirir ve saat dilimi geçerli UTC dengelemesinden (her zaman) belirlenemez ... bu nedenle bu yanıt saat dilimi bilgilerini de düşürür :-)
Martin Fido

27

Sorulan soru , azaltılmış hassasiyete sahip ISO formatıydı . Voila:

 new Date().toISOString().slice(0, 19) + 'Z'
 // '2014-10-23T13:18:06Z'

Sondaki Z'nin istendiğini varsayarsak, aksi halde atlayın.


14

En kısa, ancak Internet Explorer 8 ve öncesi tarafından desteklenmiyor:

new Date().toJSON()

12

IE7'yi desteklemeniz gerekmiyorsa, aşağıdakiler harika ve özlü bir saldırıdır:

JSON.parse(JSON.stringify(new Date()))

IE7 için bu karar json3-library ( bestiejs.github.io/json3 ) içeriyorsa da uygundur . Thanks :)
vladimir

Ayrıca IE8'de başarısız olur. ("'JSON' undefined")
Cees Timmerman

1
JSON'da yuvarlak açma çirkin, özellikle de belirttiğiniz hedef kısaltma ise; tarih toJSONyöntemini kullanın. JSON.stringifyzaten kapakların altında kullanıyor.
Mark Amery

@CeesTimmerman IE8, JSONbazı uyumluluk modlarında olmasa da nesneyi destekler . Bkz. Stackoverflow.com/questions/4715373/…
Mark Amery

3
Bu hangi açıdan daha iyidir .toISOString()?
Martin

7

Müşteriler dönüşümleri başlarında yapmaktan hoşlanmadığından genellikle bir UTC tarihi görüntülemek istemiyorum. Yerel bir ISO tarihini görüntülemek için şu işlevi kullanıyorum:

function toLocalIsoString(date, includeSeconds) {
    function pad(n) { return n < 10 ? '0' + n : n }
    var localIsoString = date.getFullYear() + '-'
        + pad(date.getMonth() + 1) + '-'
        + pad(date.getDate()) + 'T'
        + pad(date.getHours()) + ':'
        + pad(date.getMinutes()) + ':'
        + pad(date.getSeconds());
    if(date.getTimezoneOffset() == 0) localIsoString += 'Z';
    return localIsoString;
};

Yukarıdaki fonksiyon, saat dilimi ofset bilgisini atlar (yerel saat UTC olduğunda), bu nedenle yerel ofseti tek bir yerde göstermek için aşağıdaki işlevi kullanıyorum. Her seferinde ofseti göstermek istiyorsanız, çıktısını yukarıdaki işlevden sonuçlara ekleyebilirsiniz:

function getOffsetFromUTC() {
    var offset = new Date().getTimezoneOffset();
    return ((offset < 0 ? '+' : '-')
        + pad(Math.abs(offset / 60), 2)
        + ':'
        + pad(Math.abs(offset % 60), 2))
};

toLocalIsoString kullanımları pad . Gerekirse, neredeyse tüm ped işlevleri gibi çalışır, ancak tamlık uğruna kullandığım şey budur:

// Pad a number to length using padChar
function pad(number, length, padChar) {
    if (typeof length === 'undefined') length = 2;
    if (typeof padChar === 'undefined') padChar = '0';
    var str = "" + number;
    while (str.length < length) {
        str = padChar + str;
    }
    return str;
}

3

'T'den sonra bir' + 'eksik

isoDate: function(msSinceEpoch) {
  var d = new Date(msSinceEpoch);
  return d.getUTCFullYear() + '-' + (d.getUTCMonth() + 1) + '-' + d.getUTCDate() + 'T'
         + d.getUTCHours() + ':' + d.getUTCMinutes() + ':' + d.getUTCSeconds();
}

yapmalı.

Baştaki sıfırlar için bunu buradan kullanabilirsiniz :

function PadDigits(n, totalDigits) 
{ 
    n = n.toString(); 
    var pd = ''; 
    if (totalDigits > n.length) 
    { 
        for (i=0; i < (totalDigits-n.length); i++) 
        { 
            pd += '0'; 
        } 
    } 
    return pd + n.toString(); 
} 

Bu şekilde kullanmak:

PadDigits(d.getUTCHours(),2)

Büyük yakalamak! Yine de eksik "0" lara yönelik değildir.
James A. Rosen

1
Bir tamsayıyı 2 karakterli bir dizeye dönüştürmek için bir işlev yazın (bağımsız değişken 10'dan küçükse '0' ekleyerek) ve tarih / saatin her bölümü için çağırın.
dan04

3
function timeStr(d) { 
  return ''+
    d.getFullYear()+
    ('0'+(d.getMonth()+1)).slice(-2)+
    ('0'+d.getDate()).slice(-2)+
    ('0'+d.getHours()).slice(-2)+
    ('0'+d.getMinutes()).slice(-2)+
    ('0'+d.getSeconds()).slice(-2);
}

1
IE5 modunda, buradaki diğer tüm cevaplar var olmayan işlevleri kullandığından bu rotaya gitmek zorunda kaldım.
Elaskanator

3

ToISOString ile ilgili sorun tarih saatini yalnızca "Z" olarak vermesidir.

ISO-8601 ayrıca tarih saatini saat ve dakika cinsinden saat ve dakika olarak, 2016-07-16T19: 20: 30 + 5: 30 (saat dilimi UTC'den önce olduğunda) ve 2016-07-16T19: 20: 30-01 gibi biçimlerde tanımlar. : 00 (saat dilimi UTC'nin arkasındayken).

Böyle bir küçük görev için moment.js gibi başka bir eklenti kullanmak için iyi bir fikir olduğunu düşünmüyorum, özellikle de birkaç satır kodla alabiliyorsanız.



    var timezone_offset_min = new Date().getTimezoneOffset(),
        offset_hrs = parseInt(Math.abs(timezone_offset_min/60)),
        offset_min = Math.abs(timezone_offset_min%60),
        timezone_standard;

    if(offset_hrs < 10)
        offset_hrs = '0' + offset_hrs;

    if(offset_min > 10)
        offset_min = '0' + offset_min;

    // getTimezoneOffset returns an offset which is positive if the local timezone is behind UTC and vice-versa.
    // So add an opposite sign to the offset
    // If offset is 0, it means timezone is UTC
    if(timezone_offset_min < 0)
        timezone_standard = '+' + offset_hrs + ':' + offset_min;
    else if(timezone_offset_min > 0)
        timezone_standard = '-' + offset_hrs + ':' + offset_min;
    else if(timezone_offset_min == 0)
        timezone_standard = 'Z';

    // Timezone difference in hours and minutes
    // String such as +5:30 or -6:00 or Z
    console.log(timezone_standard); 

Saat dilimi saat ve dakika olarak dengelendiğinde, bir datetime dizesine ekleyebilirsiniz.

Üzerine bir blog yazısı yazdım: http://usefulangle.com/post/30/javascript-get-date-time-with-offset-hours-minutes



2

Çok daha az kodla çıktı almayı başardım.

var ps = new Date('2010-04-02T14:12:07')  ;
ps = ps.toDateString() + " " + ps.getHours() + ":"+ ps.getMinutes() + " hrs";

Çıktı:

Fri Apr 02 2010 19:42 hrs

0
function getdatetime() {
    d = new Date();
    return (1e3-~d.getUTCMonth()*10+d.toUTCString()+1e3+d/1)
        .replace(/1(..)..*?(\d+)\D+(\d+).(\S+).*(...)/,'$3-$1-$2T$4.$5Z')
        .replace(/-(\d)T/,'-0$1T');
}

Bir yerde Stack Overflow temellerini buldum (diğer bazı Stack Exchange kodu golf bir parçası olduğuna inanıyorum) ve bu yüzden Internet Explorer 10 veya daha önceki sürümlerde de çalıştığını geliştirdim. Çirkin, ama işi hallediyor.


0

Sean'ın harika ve özlü cevabını biraz şeker ve modern sözdizimiyle genişletmek için:

// date.js

const getMonthName = (num) => {
  const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Oct', 'Nov', 'Dec'];
  return months[num];
};

const formatDate = (d) => {
  const date = new Date(d);
  const year = date.getFullYear();
  const month = getMonthName(date.getMonth());
  const day = ('0' + date.getDate()).slice(-2);
  const hour = ('0' + date.getHours()).slice(-2);
  const minutes = ('0' + date.getMinutes()).slice(-2);

  return `${year} ${month} ${day}, ${hour}:${minutes}`;
};

module.exports = formatDate;

Sonra örn.

import formatDate = require('./date');

const myDate = "2018-07-24T13:44:46.493Z"; // Actual value from wherever, eg. MongoDB date
console.log(formatDate(myDate)); // 2018 Jul 24, 13:44
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.