ฉันจะส่งออกสตริงที่จัดรูปแบบ ISO 8601 ใน JavaScript ได้อย่างไร


247

ฉันมีDateวัตถุ ฉันจะแสดงtitleส่วนของตัวอย่างต่อไปนี้ได้อย่างไร

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

ฉันมีส่วน "เวลาสัมพันธ์เป็นคำพูด" จากห้องสมุดอื่น

ฉันได้ลองทำสิ่งต่อไปนี้แล้ว:

function isoDate(msSinceEpoch) {

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

}

แต่นั่นทำให้ฉัน:

"2010-4-2T3:19"

คำตอบ:


453

มีฟังก์ชั่นที่เรียกว่าtoISOString():

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

ถ้าคุณอยู่ในเบราว์เซอร์ที่ไม่รองรับฉันมีคุณ:

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 () ส่งคืนวันที่แน่นอนใน UTC หรือไม่
Jon Wells

new Date("xx").toISOString()สร้างNaN-NaN-NaNTNaN:NaN:NaN.NZการใช้งานดั้งเดิมพ่น RangeException
โจเซฟเลนน็อกซ์

หากคุณต้องการส่งวัตถุวันที่ไปยังบริการสบู่ ... นั่นคือวิธี! :) ขอบคุณ
thinklinux

1
ในตัวอย่างที่จัดทำโดย OP ไม่มีมิลลิวินาทีหรือเขตเวลา
Dan Dascalescu

ฟังก์ชันทั้งหมดที่เรียกเช่น "getUTCFullYear" ล้มเหลวเนื่องจากไม่รู้จักโหมดเอกสาร IE 5
Elaskanator

63

ดูตัวอย่างล่าสุดในหน้าhttps://developer.mozilla.org/en/Core_JavaScript_1.5_Reference:Global_Objects:Date :

/* 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">) ไม่มีเขตเวลา บางทีพวกเขาต้องการเวลาท้องถิ่นซึ่งจะเหมาะสมสำหรับสตริงเวลา UI?
Dan Dascalescu

60

เกือบทุกวิธีเป็น ISO บนเว็บจะลดข้อมูลเขตเวลาโดยใช้การแปลงเป็น "Z" เวลา ulu (UTC) ก่อนที่จะแสดงผลสตริง เบราว์เซอร์. toISOString () ดั้งเดิมของเบราว์เซอร์จะลดข้อมูลเขตเวลา

สิ่งนี้จะทิ้งข้อมูลที่มีค่าในฐานะเซิร์ฟเวอร์หรือผู้รับสามารถแปลงวันที่ ISO เต็มรูปแบบเป็นเวลา Zulu หรือเขตเวลาใดก็ตามที่ต้องการในขณะที่ยังคงได้รับข้อมูลเขตเวลาของผู้ส่ง

ทางออกที่ดีที่สุดที่ฉันเจอคือใช้ไลบรารีจาวาสคริปต์Moment.jsและใช้รหัสต่อไปนี้:

เพื่อรับเวลา ISO ปัจจุบันพร้อมข้อมูลเขตเวลาและมิลลิวินาที

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

ในการรับค่าเวลา ISO ของออบเจ็กต์วันที่ในท้องถิ่นที่มีข้อมูลเขตเวลา แต่ไม่มีมิลลิวินาที

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

สิ่งนี้สามารถใช้ร่วมกับ Date.js เพื่อรับฟังก์ชั่นเช่น Date.today () ซึ่งผลลัพธ์จะถูกส่งไปยังช่วงเวลา

สตริงวันที่จัดรูปแบบเช่นนี้เป็นคอมไพเลอร์ JSON และให้ยืมตัวเองดีที่จะได้รับการจัดเก็บลงในฐานข้อมูล Python และ C # ดูเหมือนจะชอบมัน


21
ไม่ได้อยู่กับคนเดท เพียงแค่ใช้ moment.js และช่วยผมของคุณ
Valamas

1
จริง ๆ แล้วบนไพ ธ อนและเดซิเบลมันกลับกลายเป็นความเจ็บปวด db ใช้ UTC (ไม่มีปัญหาเนื่องจากคุณสามารถแปลงเป็นฝั่งเซิร์ฟเวอร์ UTC ได้อย่างง่ายดาย) ดังนั้นหากคุณต้องการเก็บข้อมูลออฟเซ็ตคุณต้องการฟิลด์อื่น และงูใหญ่ชอบใช้ nanoseconds แทนที่จะเป็นมิลลิวินาทีของ javascript ซึ่งมักจะเพียงพอและดีกว่าในช่วงไม่กี่วินาที บนไพธ อน dateutil.parser.parseจะวิเคราะห์คำได้อย่างถูกต้องและการเขียนมิลลิวินาที ISO ต้องใช้ "_when = when.strftime ("% Y-% m-% dT% H:% M:% S. % f% z "); return _when [: - 8] + _when [-5:]" เพื่อแปลง nanos เป็น millis นั่นไม่ดีเลย
Daniel F

3
moment(new Date()).format()คุณสามารถจริงเพียงละเว้นรูปแบบเช่นดังนั้น: "ตั้งแต่เวอร์ชั่น 1.5.0 การโทรช่วงเวลา # รูปแบบที่ไม่มีรูปแบบจะเริ่มต้นเป็น ... รูปแบบ ISO8601 YYYY-MM-DDTHH:mm:ssZ" Doc: เลื่อนขึ้นจากmomentjs.com/docs/#/displaying/fromnow
user193130

1
Good point @ user193130 แต่คุณต้องระวังให้ดีเพราะผลลัพธ์นั้นแตกต่างจากวิธีเนทีฟ moment().format() "2015-03-04T17:16:05+03:00" (new Date()).toISOString() "2015-03-04T14:16:24.555Z"
Olga

1
อาจจะเป็นเรื่องพิถีพิถัน แต่ตัวอย่างเหล่านี้จะคืนค่าออฟเซ็ตปัจจุบันจาก UTC ไม่ใช่เขตเวลา เขตเวลาเป็นภูมิภาคทางภูมิศาสตร์ที่มักแสดงเช่น "อเมริกา / โตรอนโต" เขตเวลาจำนวนมากเปลี่ยน UTC offset ของพวกเขาปีละสองครั้งและเขตเวลาไม่สามารถ (เสมอ) จะถูกกำหนดจาก UTC offset ในปัจจุบัน ... ดังนั้นคำตอบนี้ก็ยังส่งข้อมูลเขตเวลา :-)
Martin Fido

27

คำถามที่ถามคือรูปแบบ ISO พร้อมความแม่นยำที่ลดลง voila:

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

สมมติว่าต้องการ Z ต่อท้ายมิฉะนั้นจะข้ามไป


14

สั้นที่สุด แต่ไม่รองรับโดย Internet Explorer 8 และรุ่นก่อนหน้า:

new Date().toJSON()

12

หากคุณไม่ต้องการรองรับ IE7 ต่อไปนี้เป็นแฮ็คที่กระชับและยอดเยี่ยม:

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

สำหรับ IE7 การตัดสินใจนี้ก็เหมาะสมเช่นกันหากรวม json3-library ( bestiejs.github.io/json3 ) ขอบคุณ :)
vladimir

ยังล้มเหลวใน IE8 ("'JSON' ไม่ได้กำหนด")
Cees Timmerman

1
การปัดเศษผ่าน JSON นั้นน่าเกลียดโดยเฉพาะอย่างยิ่งหากเป้าหมายที่ระบุไว้ของคุณนั้นกระชับ ใช้toJSONวิธีของวันที่แทน JSON.stringifyใช้มันภายใต้ฝาปิดอยู่ดี
Mark Amery

@CeesTimmerman IE8 รองรับJSONวัตถุแม้ว่าจะไม่ได้อยู่ในโหมดการทำงานร่วมกันบางอย่าง ดู stackoverflow.com/questions/4715373/…
ทำเครื่องหมาย Amery

3
สิ่งนี้ดีกว่า.toISOString()อะไร?
Martin

7

โดยทั่วไปฉันไม่ต้องการแสดงวันที่ UTC เนื่องจากลูกค้าไม่ชอบทำ Conversion ในหัวของพวกเขา เพื่อแสดงวันที่ ISO ในพื้นที่ฉันใช้ฟังก์ชั่น:

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

ฟังก์ชั่นด้านบนละเว้นข้อมูลการชดเชยเขตเวลา (ยกเว้นถ้าเวลาท้องถิ่นเกิดขึ้นกับ UTC) ดังนั้นฉันจึงใช้ฟังก์ชั่นด้านล่างเพื่อแสดงการชดเชยในท้องถิ่นในสถานที่เดียว นอกจากนี้คุณยังสามารถผนวกผลลัพธ์ไปยังผลลัพธ์จากฟังก์ชันด้านบนหากคุณต้องการแสดงออฟเซ็ตในแต่ละครั้ง:

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

toLocalIsoString การใช้งาน padการใช้งานถ้าจำเป็นมันใช้งานได้เกือบทุกฟังก์ชั่นแผ่น แต่เพื่อความสมบูรณ์นี่คือสิ่งที่ฉันใช้:

// 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'

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

ควรทำมัน

สำหรับศูนย์นำคุณสามารถใช้สิ่งนี้จากที่นี่ :

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

ใช้แบบนี้:

PadDigits(d.getUTCHours(),2)

เยี่ยมมาก! ถึงแม้ว่ามันจะไม่จัดการกับ "0" ที่ขาดหายไป
James A. Rosen

1
เขียนฟังก์ชั่นเพื่อแปลงจำนวนเต็มเป็นสตริง 2 อักขระ (การเติม '0' ถ้าอาร์กิวเมนต์น้อยกว่า 10) และเรียกใช้สำหรับแต่ละส่วนของวันที่ / เวลา
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 ฉันต้องไปเส้นทางนี้เนื่องจากคำตอบอื่น ๆ ทั้งหมดที่นี่ใช้ฟังก์ชั่นที่ไม่มี
Elaskanator

3

ปัญหากับ toISOString คือมันให้ datetime เพียงเป็น "Z"

ISO-8601 ยังกำหนดวันที่และเวลาด้วยความแตกต่างของเขตเวลาเป็นชั่วโมงและนาทีในรูปแบบเช่น 2016-07-16T19: 20: 30 + 5: 30 (เมื่อเขตเวลาอยู่ข้างหน้า UTC) และ 2016-07-16T19: 20: 30-01 : 00 (เมื่อเขตเวลาหลัง UTC)

ฉันไม่คิดว่ามันเป็นความคิดที่ดีที่จะใช้ปลั๊กอินอื่น moment.js สำหรับงานเล็ก ๆ โดยเฉพาะอย่างยิ่งเมื่อคุณได้รับมันด้วยโค้ดสองสามบรรทัด



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

เมื่อคุณมีการชดเชยเขตเวลาเป็นชั่วโมงและนาทีคุณสามารถผนวกเข้ากับสตริงวันที่และเวลา

ฉันเขียนบทความในบล็อก: http://usefulangle.com/post/30/javascript-get-date-time-with-offset-hours-minutes



2

ฉันสามารถรับผลลัพธ์ด้านล่างด้วยรหัสน้อยมาก

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

เอาท์พุท:

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

ฉันพบพื้นฐานเกี่ยวกับ Stack Overflow บางแห่ง (ฉันเชื่อว่ามันเป็นส่วนหนึ่งของการเล่นรหัส Stack Exchange อื่น ๆ ) และฉันได้ปรับปรุงมันเพื่อให้ทำงานบน Internet Explorer 10 หรือเก่ากว่าได้ มันน่าเกลียด แต่ก็ทำให้งานเสร็จ


0

เพื่อขยายคำตอบที่ดีและกระชับของฌอนด้วยน้ำตาลและรูปแบบที่ทันสมัย:

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

จากนั้นเช่น

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.