如何在JavaScript中格式化日期?

3464
如何将JavaScript的Date对象格式化为字符串?(最好的格式是:10-Aug-2010)

330
跟往常一样:请注意月份是从零开始计算的!因此,一月是零而不是一... - Christophe Roussy
34
请注意,myDate.getDay()并不返回一周中的星期几,而是返回星期几在这周中的位置myDate.getDate()返回的是当前日期的星期几 - Jimenemex
15
你可以使用 toLocaleDateString - onmyway133
5
@onmyway,实际上你不能这样做。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleFormat - ahnbizcad
1
如果您想要将字符串解析为日期对象,请参阅在JavaScript中将字符串解析为日期 - Sebastian Simon
显示剩余3条评论
70个回答

2977

如果您需要比当前接受的答案更少的格式控制,可以使用Date#toLocaleDateString来创建标准的区域设置特定渲染。 localeoptions参数允许应用程序指定应使用其格式约定的语言,并允许对呈现进行一些自定义。

选项键示例:

  • day:
    日期的表示方式。
    可能的取值有"数字","两位数"。
  • weekday:
    星期几的表示方式。
    可能的取值有"紧缩","简短","完整"。
  • year:
    年份的表示方式。
    可能的取值有"数字","两位数"。
  • month:
    月份的表示方式。
    可能的取值有"数字","两位数","紧缩","简短","完整"。
  • hour:
    小时的表示方式。
    可能的取值有"数字","两位数"。
  • minute: 分钟的表示方式。
    可能的取值有"数字","两位数"。
  • second:
    秒钟的表示方式。
    可能的取值有"数字","两位数"。
  • hour12:
    时间格式的表示方式。
    接受布尔值true或false。
  • 所有这些键都是可选的。您可以根据自己的需求更改选项值的数量,这也将反映每个日期时间术语的存在。

    注意:如果您只想配置内容选项,但仍要使用当前区域设置,则将第一个参数传递为null将导致错误。请改用undefined

    不同语言的示例:

    1. "en-US": 用于美式英语
    2. "en-GB": 用于英式英语
    3. "hi-IN": 用于印地语
    4. "ja-JP": 用于日语

    您可以使用更多语言选项。

    例如

    var options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
    var today  = new Date();
    
    console.log(today.toLocaleDateString("en-US")); // 9/17/2016
    console.log(today.toLocaleDateString("en-US", options)); // Saturday, September 17, 2016
    console.log(today.toLocaleDateString("hi-IN", options)); // शनिवार, 17 सितंबर 2016

    您也可以使用 toLocaleString() 方法来实现相同的目的。唯一的区别是,当您不传递任何选项时,此函数提供时间信息。

    // Example
    9/17/2016, 1:21:34 PM
    

    参考资料:


    41
    这个答案似乎应该是目前最好的答案。同时使用了选项“hour12: true”来使用12小时制而非24小时制。也许应该将其添加到您的回答摘要列表中。 - Doug Knudsen
    37
    这个答案没有提到,但你可以使用toLocaleDateString来返回你想要的特定部分,然后按照自己的需要进行拼接。请查看我下面的答案。date.toLocaleDateString("en-US", { day: 'numeric' }) + "-"+ date.toLocaleDateString("en-US", { month: 'short' }) + "-" + date.toLocaleDateString("en-US", { year: 'numeric' })应该会得到16-Nov-2019 - K Vij
    8
    挖了很久的链接,但我找到了他们隐藏的地方@MosesSchwartz: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat - btalb
    6
    @KVij 这种方式格式化日期非常低效,特别是考虑到有一个 formatToParts 方法,可以返回所有部分的对象数组。请使用该方法。 - RobG
    2
    请注意文档中的以下信息:“要使用浏览器的默认语言环境,请传递一个空数组”(用于语言环境参数)。 - Peter Gerdes
    显示剩余5条评论

    1726
    对于自定义分隔的日期格式,您需要从DateTimeFormat对象(它是ECMAScript国际化API的一部分)中提取日期(或时间)组件,然后手动创建一个带有所需分隔符的字符串。
    要做到这一点,您可以使用DateTimeFormat#formatToParts。您可以解构数组,但这并不理想,因为数组输出取决于区域设置。

    { // example 1
       let formatter = new Intl.DateTimeFormat('en');
       let example = formatter.formatToParts();
       console.log(example);
    }
    { // example 2
       let formatter = new Intl.DateTimeFormat('hi');
       let example = formatter.formatToParts();
       console.log(example);
    }

    更好的做法是将一个格式数组映射到结果字符串中:

    function join(date, options, separator) {
       function format(option) {
          let formatter = new Intl.DateTimeFormat('en', option);
          return formatter.format(date);
       }
       return options.map(format).join(separator);
    }
    
    let options = [{day: 'numeric'}, {month: 'short'}, {year: 'numeric'}];
    let joined = join(new Date, options, '-');
    console.log(joined);

    你还可以使用DateTimeFormat#format逐个提取DateTimeFormat的部分,但请注意,截至2020年3月,ECMAScript实现中存在一个关于分钟和秒钟前导零的bug(这个问题可以通过上述方法绕过)。

    let date = new Date(2010, 7, 5);
    let year = new Intl.DateTimeFormat('en', { year: 'numeric' }).format(date);
    let month = new Intl.DateTimeFormat('en', { month: 'short' }).format(date);
    let day = new Intl.DateTimeFormat('en', { day: '2-digit' }).format(date);
    console.log(`${day}-${month}-${year}`);

    在处理日期和时间时,通常值得使用一个库(例如luxondate-fnsmoment.js 不推荐用于新项目),因为该领域存在许多隐藏的复杂性。
    请注意,上述解决方案中使用的ECMAScript国际化API不支持IE10(2020年2月全球浏览器市场份额为0.03%)。

    2
    或者扩展Date对象,就像我在https://dev59.com/l07Sa4cB1Zd3GeqP7eJ2#3189792中所做的那样。 - Marcel Korpel
    60
    我知道ye代表年,mo代表月,da代表日。那么o代表什么?a又代表什么?m又是什么呢?请使用适当的变量命名。 - mikemaccana
    3
    这是我个人认为最好的答案(最后一段代码片段),因为它允许在任何格式下灵活使用,即您不需要寻找满足您需求的国家代码。 - João Pimentel Ferreira
    1
    答案是正确的,但变量名称的懒惰程度真的是另一个层次。他写成了“da”而不是“day”。适当的变量名称会非常好! - Simon S.
    1
    @fudo 虽然 momentjs 没有被弃用,但它的作者认为它已经“被遗弃”。他们不再维护或改进这个库。它非常庞大,并且会引起与流行的 JS 框架(如 Angular 或 React)的问题,因此正在被其他选项所取代。 - Rekesoft
    显示剩余2条评论

    772

    如果您需要使用纯JavaScript快速格式化日期,请使用getDategetMonth + 1getFullYeargetHoursgetMinutes

    var d = new Date();
    
    var datestring = d.getDate()  + "-" + (d.getMonth()+1) + "-" + d.getFullYear() + " " +
    d.getHours() + ":" + d.getMinutes();
    
    // 16-5-2015 9:50
    

    或者,如果你需要在前面加上0:

    var datestring = ("0" + d.getDate()).slice(-2) + "-" + ("0"+(d.getMonth()+1)).slice(-2) + "-" +
        d.getFullYear() + " " + ("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2);
    
    // 16-05-2015 09:50
    

    53
    你可以使用 .toString().padStart(2, '0') 来补足零位。 - Benny Jobigan
    6
    值得一提的是,String.padStart() 只能在 ECMAScript 2017 中使用。 - JHH
    1
    使用ES6模板字面量和辅助函数let pad = v => `0${v}`.slice(-2);,可以将填充版本简化为:let datestring = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}_${pad(d.getHours())}-${pad(d.getMinutes())}`; - klues

    703

    他的“L”毫秒代码是错误的,他应该删除“L > 99?”这部分...除此之外,它相当整洁,但本地化效果不太好。 - user2451227
    9
    这个解决方案也可以作为 npm 包获得:https://www.npmjs.com/package/dateformat - David
    14
    如果你要麻烦地引入一个外部依赖,我建议使用moment.js。它可以进行这种类型的日期格式化:https://momentjs.com/docs/#/displaying/ 且具有更多的功能。 - Drew Dara-Abrams
    时区与 Date API 相比,在日期格式方面也表现良好,特别是在 IE 中。 - Sandeep Kumar
    虽然几年前包含Moment.js是可以的,但它目前已停止维护:https://momentjs.com/docs/#/-project-status/ - Heretic Monkey

    579

    我想要将今天的日期转换为一个像2012-06-23这样的适用于MySQL的日期字符串,并将该字符串用作我的查询参数之一。我找到的简单解决方案是:

    var today = new Date().toISOString().slice(0, 10);
    

    请记住,上面的解决方案不会考虑您的时区偏移量。

    您可以考虑使用此函数代替:

    function toJSONLocal (date) {
        var local = new Date(date);
        local.setMinutes(date.getMinutes() - date.getTimezoneOffset());
        return local.toJSON().slice(0, 10);
    }
    

    如果你在一天的开始/结束附近执行此代码,它将为您提供正确的日期。

    var date = new Date();
    
    function toLocal(date) {
      var local = new Date(date);
      local.setMinutes(date.getMinutes() - date.getTimezoneOffset());
      return local.toJSON();
    }
    
    function toJSONLocal(date) {
      var local = new Date(date);
      local.setMinutes(date.getMinutes() - date.getTimezoneOffset());
      return local.toJSON().slice(0, 10);
    }
    
    // check out your devtools console
    console.log(date.toJSON());
    console.log(date.toISOString());
    console.log(toLocal(date));
    
    console.log(toJSONLocal(date));


    18
    你可以使用new Date(date + " UTC")来欺骗时区,同时可以省略掉setMinutes这一行代码。哎呀,JavaScript 真是有点混乱。 - Vajk Hermecz
    28
    Y10K兼容版本:var today = new Date().toISOString().slice(0,-14) :) (翻译:这是一段JavaScript代码,用于获取当前日期并将其格式化为ISO标准格式。它会将日期转换为字符串,并去掉最后14个字符以去除时间信息。Y10K兼容表示该代码可以处理距今10000年后的日期。笑脸表情是作者在文本末尾加入的一个积极的符号。) - Alex Shaffer
    33
    或者像这样 new Date().toISOString().split('T')[0] - rofrol
    9
    new Date().toISOString().slice(0, 19).replace('T',' ') 可以包含时间信息。 - Gerrie van Wyk
    10
    评论一下,时区的缺失不是某种“在一天的开始/结束周围”的小不便。例如,在澳大利亚,直到上午约11点左右,日期可能仍然是错误的——接近一天的一半时间! - Steve Bennett
    显示剩余4条评论

    423

    自定义格式化函数:

    对于固定格式,可以使用一个简单的函数来完成任务。以下示例生成国际格式 YYYY-MM-DD:

    function dateToYMD(date) {
        var d = date.getDate();
        var m = date.getMonth() + 1; //Month from 0 to 11
        var y = date.getFullYear();
        return '' + y + '-' + (m<=9 ? '0' + m : m) + '-' + (d <= 9 ? '0' + d : d);
    }
    
    console.log(dateToYMD(new Date(2017,10,5))); // Nov 5

    OP格式可以生成如下:

    function dateToYMD(date) {
        var strArray=['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
        var d = date.getDate();
        var m = strArray[date.getMonth()];
        var y = date.getFullYear();
        return '' + (d <= 9 ? '0' + d : d) + '-' + m + '-' + y;
    }
    console.log(dateToYMD(new Date(2017,10,5))); // Nov 5

    注意:然而,通常不推荐扩展JavaScript标准库(例如将此函数添加到Date原型中)。

    更高级的函数可以根据格式参数生成可配置的输出。

    如果编写格式化函数太长了,有很多库可以完成它。其他答案已经列举了一些。但增加依赖也有其代价。

    标准ECMAScript格式化函数:

    自ECMAScript的较新版本以来,Date类具有一些特定的格式化函数:

    toDateString: Implementation dependent, show only the date.

    https://262.ecma-international.org/#sec-date.prototype.todatestring

    new Date().toDateString(); // e.g. "Fri Nov 11 2016"
    

    toISOString: Show ISO 8601 date and time.

    https://262.ecma-international.org/#sec-date.prototype.toisostring

    new Date().toISOString(); // e.g. "2016-11-21T08:00:00.000Z"
    

    toJSON: Stringifier for JSON.

    https://262.ecma-international.org/#sec-date.prototype.tojson

    new Date().toJSON(); // e.g. "2016-11-21T08:00:00.000Z"
    

    toLocaleDateString: Implementation dependent, a date in locale format.

    https://262.ecma-international.org/#sec-date.prototype.tolocaledatestring

    new Date().toLocaleDateString(); // e.g. "21/11/2016"
    

    toLocaleString: Implementation dependent, a date&time in locale format.

    https://262.ecma-international.org/#sec-date.prototype.tolocalestring

    new Date().toLocaleString(); // e.g. "21/11/2016, 08:00:00 AM"
    

    toLocaleTimeString: Implementation dependent, a time in locale format.

    https://262.ecma-international.org/#sec-date.prototype.tolocaletimestring

    new Date().toLocaleTimeString(); // e.g. "08:00:00 AM"
    

    toString: Generic toString for Date.

    https://262.ecma-international.org/#sec-date.prototype.tostring

    new Date().toString(); // e.g. "Fri Nov 21 2016 08:00:00 GMT+0100 (W. Europe Standard Time)"
    

    注:可以通过这些格式化生成自定义输出。

    new Date().toISOString().slice(0,10); //return YYYY-MM-DD
    

    Examples snippets:

    console.log("1) "+  new Date().toDateString());
    console.log("2) "+  new Date().toISOString());
    console.log("3) "+  new Date().toJSON());
    console.log("4) "+  new Date().toLocaleDateString());
    console.log("5) "+  new Date().toLocaleString());
    console.log("6) "+  new Date().toLocaleTimeString());
    console.log("7) "+  new Date().toString());
    console.log("8) "+  new Date().toISOString().slice(0,10));

    为标准函数指定语言环境:

    上述某些标准函数依赖于语言环境:

    • toLocaleDateString()
    • toLocaleTimeString()
    • toLocalString()

    这是因为不同的文化会使用不同的格式,并以不同的方式表达其日期或时间。 该函数默认返回设备所配置的格式,但可以通过设置参数(ECMA-402)来指定其格式。

    toLocaleDateString([locales[, options]])
    toLocaleTimeString([locales[, options]])
    toLocaleString([locales[, options]])
    //e.g. toLocaleDateString('ko-KR');
    
    选项的第二个参数允许在所选语言环境中配置更具体的格式。例如,月份可以显示为全文本或缩写形式。
    toLocaleString('en-GB', { month: 'short' })
    toLocaleString('en-GB', { month: 'long' })
    

    Examples snippets:

    console.log("1) "+  new Date().toLocaleString('en-US'));
    console.log("2) "+  new Date().toLocaleString('ko-KR'));
    console.log("3) "+  new Date().toLocaleString('de-CH'));
    
    console.log("4) "+  new Date().toLocaleString('en-GB', { hour12: false }));
    console.log("5) "+  new Date().toLocaleString('en-GB', { hour12: true }));

    关于本地化的一些良好实践:

    • 大多数人不喜欢以外国的格式显示日期,因此尽可能保留默认语言环境(而非在所有地方设置'en-US')。
    • 实现与UTC之间的转换可能具有挑战性(考虑到DST、时区不是1小时的倍数等)。尽可能使用经过充分测试的库。
    • 不要假设语言环境与国家相关:某些国家有很多语言环境(如加拿大、印度等)
    • 避免通过非标准方式检测语言环境。在这里,您可以阅读有关多个问题的信息:检测键盘布局,通过地理位置检测语言环境等。

    Intl.DateTimeFormat() 构造函数支持的参数在此链接中列出:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat。 - ino
    .toJSON() 在内部使用.toISOString()方法 (根据文档)。需要注意的是,ISO转换会转换为另一个时区,这可能会更改日期部分(请参见其他评论)。此外,似乎OP想要将其转换为Oracle(等)的“区域设置/文化”,而不是人类文化... - frIT
    答案足够通用,适用于计算机表示和人类可读。我还要重申,当夏令时切换(每年两次)时,UTC转换可能会产生棘手的影响,从而使任何错误难以检测到。 - Adrian Maire

    189
    如果您的项目中已经使用了jQuery UI,那么您可以这样做:

    如果您已经在项目中使用jQuery UI,您可以这样做:

    var formatted = $.datepicker.formatDate("M d, yy", new Date("2014-07-08T09:02:21.377"));
    
    // formatted will be 'Jul 8, 2014'
    

    这里提供了一些可供使用的日期选择器日期格式选项,请点击此处查看。


    170

    注意(2022年10月): toLocaleFormat 早已被弃用,自 Firefox 版本58起已被移除。请参见toLocaleFormat

    我认为你可以直接使用非标准的 Date 方法 toLocaleFormat(formatString)

    formatString:格式字符串应符合C语言中strftime()函数所期望的相同格式。

    var today = new Date();
    today.toLocaleFormat('%d-%b-%Y'); // 30-Dec-2011
    

    参考资料:


    187
    toLocaleFormat() 似乎仅在 Firefox 中有效。我在 IE 和 Chrome 上都无法使用。 - fitzgeraldsteele
    16
    Chrome有.toLocaleString('en')方法。似乎新浏览器也支持此方法。https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString - apocalypz
    8
    阅读此处的警告: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleFormat - Carson Reinke
    8
    7年后,这个函数在其他浏览器中仍然无法使用,并且在Firefox中已被弃用。Deprecated_toLocaleFormat - Manuel Ortiz
    2
    自2021年12月起已被弃用。 - Lle.4
    显示剩余3条评论

    124

    对于小的一次性任务,纯JavaScript是最好的选择。

    另一方面,如果你需要更多的日期处理功能,MomentJS是一个很好的解决方案。

    例如:

    moment().format('YYYY-MM-DD HH:m:s');     // now() -> 2015-03-24 14:32:20
    moment("20111031", "YYYYMMDD").fromNow(); // 3 years ago
    moment("20120620", "YYYYMMDD").fromNow(); // 3 years ago
    moment().startOf('day').fromNow();        // 11 hours ago
    moment().endOf('day').fromNow();          // in 13 hours
    

    4
    重要提醒:除非您了解 YYYYyyyy 之间的差别,否则请勿使用 YYYY。请注意:若不了解 YYYYyyyy 的区别,请勿使用 YYYY - Domin
    1
    @Domin 这个问题与iOS中的NSDateFormatter有关,例如从Objective-C或Swift使用。这个问题是关于浏览器中的Javascript,而这个答案使用MomentJS,在其中YYYY(而不是yyyy)是标准年份,GGGG(而不是YYYY)是基于ISO的周年份。 - Mark Reed

    118
    在现代浏览器(*)中,您只需执行以下操作:
    var today = new Date().toLocaleDateString('en-GB', {
        day : 'numeric',
        month : 'short',
        year : 'numeric'
    }).split(' ').join('-');
    

    如果在今天执行(2016年1月24日)则输出:

    '24-Jan-2016'
    

    (*) 根据MDN的定义, "现代浏览器"指的是Chrome 24+、Firefox 29+、Internet Explorer 11、Edge 12+、Opera 15+和Safari 夜间版本


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接