将JavaScript日期格式化为yyyy-mm-dd。

1135

我有一个格式为Sun May 11,2014的日期。如何使用JavaScript将其转换为2014-05-11

function taskDate(dateMilli) {
    var d = (new Date(dateMilli) + '').split(' ');
    d[2] = d[2] + ',';

    return [d[0], d[1], d[2], d[3]].join(' ');
}

var datemilli = Date.parse('Sun May 11,2014');
console.log(taskDate(datemilli));

上面的代码给了我相同的日期格式,sun may 11,2014。我该怎么解决?


真的考虑使用像 Moment.js 这样的库。它可以格式化出所需的结果 :) - Ankur
14
为什么要用一个库,只需五行代码就可以完成工作? @Ankur - Black Mamba
可能是在JavaScript中格式化日期的文档在哪里?的重复问题。 - Heretic Monkey
相关:JavaScript中有效的日期时间字符串是什么? 请注意,“Sun May 11,2014”不是一个有效的日期字符串,解析它可能会在某些浏览器中失败。 - str
@Black Mamba 为什么要使用库,当只需要几行代码就可以解决问题呢? - Maxim Therrien
类似格式 2/21/22, 7:45 AMdate.toLocaleString([], { dateStyle: 'short', timeStyle: 'short' }) 参考:https://dev59.com/ymMm5IYBdhLWcg3wDbmo#71210314 - Alex Szücs
54个回答

1487

只需利用内置的 toISOString 方法即可将日期转换为 ISO 8601 格式:

let yourDate = new Date()
yourDate.toISOString().split('T')[0]

其中yourDate是你的日期对象。

编辑: @exbuddha评论中提供了处理时区的方法:

const offset = yourDate.getTimezoneOffset()
yourDate = new Date(yourDate.getTime() - (offset*60*1000))
return yourDate.toISOString().split('T')[0]

454
请注意这种方法首先将日期转换为UTC。如果您处于+时区并且时间部分早于一天,那么它可能会回滚一天。另外,如果您处于-时区并且时间部分晚于一天,那么它可能会提前一天。 - Luke Baulch
21
尝试使用以下代码替换:new Date(yourDateStr).toISOString().split('T')[0]。该代码可将日期字符串转换为ISO 8601格式的日期,并返回仅包含日期部分的子字符串。 - exbuddha
55
const offset = yourDate.getTimezoneOffset(); yourDate = new Date(yourDate.getTime() + (offset*60*1000)); yourDate.toISOString().split('T')[0]这将解决时区问题。 - mjwrazor
36
now.toISOString().substring(0,10); 的翻译是:这是一种更为简洁的方法,它提醒你完整的ISO格式中的前十个字符是 YYYY-MM-DD - Gutimore
19
注意:使用 @mjwrazor 提供的有用解决方案后,我需要减去偏移量而不是加上偏移量才能得到正确的日期(将 + (offset 修改为 - (offset)。 - rococo
显示剩余12条评论

966

你可以做以下操作:

function formatDate(date) {
    var d = new Date(date),
        month = '' + (d.getMonth() + 1),
        day = '' + d.getDate(),
        year = d.getFullYear();

    if (month.length < 2) 
        month = '0' + month;
    if (day.length < 2) 
        day = '0' + day;

    return [year, month, day].join('-');
}
 
console.log(formatDate('Sun May 11,2014'));

使用示例:

console.log(formatDate('Sun May 11,2014'));

输出:

2014-05-11

JSFiddle上的演示:http://jsfiddle.net/abdulrauf6182012/2Frm3/


39
同一语句中真的可以声明多个变量吗?https://dev59.com/yHRB5IYBdhLWcg3wLkxM - bhspencer
30
在同一语句中多次声明变量不仅仅是美学风格的偏好,它是一种危险的做法。如果你无意中遗漏了每个声明后面的逗号,就会创建全局变量。这并不是应该鼓励的行为,特别是当这段代码可能成为问题的标准答案时。 - bhspencer
19
"use strict" 是 JavaScript 中的一个指令,表示代码应该以严格模式运行。它会启用更严格的语法和错误检查,并禁用一些不安全或不建议使用的特性。 - Vix
5
重新格式化日期字符串不应该依赖于内置解析器对非标准字符串的成功解析。鉴于原始格式,可以在不使用Date的情况下用更少的代码重新格式化它。 - RobG
43
这个方法非常有效,但我不明白为什么JavaScript没有本地的解决方案…我的意思是,我们已经到了2020年,日期对于Web应用程序来说是一个重要的方面。 - babaliaris
显示剩余5条评论

384

我用这种方式获取日期的格式为 yyyy-mm-dd :)

var todayDate = new Date().toISOString().slice(0, 10);
console.log(todayDate);


22
你如何处理这里@Luke_Baulch提到的日期向后推迟一天的情况? - Malvineous
11
你可以这样做:var todayDate = new Date();todayDate.setMinutes(todayDate.getMinutes() - todayDate.getTimezoneOffset());todayDate.toISOString().slice(0,10);这将有助于避免UTC问题。 - Mitch3091
3
有一个疑问,我们如何知道需要减去或加上偏移量? - whyAto8
14
有时候不起作用。由于UTC转换,它有时会减去一天。 - NickG
2
UTC!!!在澳大利亚,我们处于+10时区。因为我倾向于在下午修复问题,所以花了我一个星期才找到这个问题。 - KenF
显示剩余3条评论

376

2020年的答案

您可以使用本地.toLocaleDateString()函数,该函数支持几个有用的参数,如locale(选择格式,如MM/DD/YYYY或YYYY/MM/DD)、timezone(转换日期)和formats details options(例如:1 vs 01 vs January)。

示例

const testCases = [
  new Date().toLocaleDateString(), // 8/19/2020
  new Date().toLocaleString(undefined, {year: 'numeric', month: '2-digit', day: '2-digit', weekday:"long", hour: '2-digit', hour12: false, minute:'2-digit', second:'2-digit'}), // 'Wednesday, 14/06/2023, 13:43:57'
  new Date().toLocaleDateString('en-US', {year: 'numeric', month: '2-digit', day: '2-digit'}), // 08/19/2020 (month and day with two digits)
  new Date().toLocaleDateString('en-ZA'), // 2020/08/19 (year/month/day) notice the different locale
  new Date().toLocaleDateString('en-CA'), // 2020-08-19 (year-month-day) notice the different locale
  new Date().toLocaleString("en-US", {timeZone: "America/New_York"}), // 8/19/2020, 9:29:51 AM. (date and time in a specific timezone)
  new Date().toLocaleString("en-US", {hour: '2-digit', hour12: false, timeZone: "America/New_York"}),  // 09 (just the hour)
]

for (const testData of testCases) {
  console.log(testData)
}

请注意,有时为了以您特定的格式输出日期,您需要找到与该格式兼容的区域设置。 您可以在此处找到区域设置示例:https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_tolocalestring_date_all 请注意,区域设置只会改变格式,如果您想将特定日期转换为特定国家或城市的时间等效值,则需要使用时区参数。

13
对于我这种不需要时区的情况,new Date().toLocaleDateString('en-CA')非常完美。 - Qarun Qadir Bissoondial
15
.toLocaleDateString('en-CA')的确切格式在较新的浏览器中会出现问题,因此不具备可移植性!最近,在 ICU 72(Chrome 110 和 Firefox 110 beta)的浏览器中,它从yyyy-MM-dd更改为M/d/yyyy。不要对特定地区的格式进行假设。请使用基于.toISOString()的其中一个答案。 - undefined
14
.toLocaleDateString('en-CA') 的确切格式不具可移植性,会在较新的浏览器中出现问题!它最近已经从 ICU 72(Chrome 110和Firefox 110 beta)中的 yyyy-MM-dd 更改为 M/d/yyyy。不要对特定区域设置的具体格式做出假设,使用基于 .toISOString() 的其中一个答案即可。 - Anders Kaseorg
3
@SamBarnum 这并不是应该从中学到的教训。不能保证 sv-SE 将来不会改变。如果你需要解析结果,请使用 .toISOString() - Anders Kaseorg
2
这个回答并没有直接回答问题。主要意思是“试试使用非默认的区域设置”……即使如此,在给出的许多(无关的)示例中也没有明确的解决方案。 - Bin Ury
显示剩余14条评论

228

将日期转换为 yyyy-mm-dd 格式的最简单方法是这样的:

var date = new Date("Sun May 11,2014");
var dateString = new Date(date.getTime() - (date.getTimezoneOffset() * 60000 ))
                    .toISOString()
                    .split("T")[0];

工作原理:

  • new Date("Sun May 11,2014") 将字符串 "Sun May 11,2014" 转换为一个日期对象,该对象代表了基于当前语言环境(主机系统设置)的时区中的时间 Sun May 11 2014 00:00:00
  • new Date(date.getTime() - (date.getTimezoneOffset() * 60000 )) 通过减去时区偏移量,将您的日期转换为与协调世界时(标准时间)中的时间 Sun May 11 2014 00:00:00 对应的日期对象
  • .toISOString() 将日期对象转换为 ISO 8601 字符串 2014-05-11T00:00:00.000Z
  • .split("T") 将字符串拆分成数组 ["2014-05-11", "00:00:00.000Z"]
  • [0] 获取该数组的第一个元素

演示

var date = new Date("Sun May 11,2014");
var dateString = new Date(date.getTime() - (date.getTimezoneOffset() * 60000 ))
                    .toISOString()
                    .split("T")[0];

console.log(dateString);

注意:

如果您的输入格式与原始问题不同,代码的第一部分(new Date(...))可能需要进行微调。正如评论中mikeypie所指出的那样,如果日期字符串已经处于预期的输出格式,并且本地时区在UTC之西,则new Date('2022-05-18')的结果为2022-05-17。用户的语言环境(例如MM/DD/YYYYDD-MM-YYYY)也可能会影响new Date(...)对日期的解析方式。因此,如果您想将此代码用于不同的输入格式,请进行适当的测试。


87
没人感到惊讶,这难道不是最简单的方法吗? - gap
2
@JoeDevmon:我不明白这与此有何关系。-(date.getTimezoneOffset() * 60000)这一部分应该消除任何时区差异,包括夏令时的影响。 - John Slegers
2
@JohnSlegers,这正是我所想的,但在某些情况下,我仍然得到前一天的日期。我进行了重构,你的示例现在可以工作了。我可能有一个奇怪的日期字符串或其他什么问题。感谢您的耐心指导和指出问题。+1 - Joe's Ideas
3
我在 Stack Overflow 和其他网站上搜索了很久,以找到在 JS 中处理日期时最好的处理时区问题的方法,毫无疑问,这是迄今为止最简单和最好的方法。谢谢! - HartleySan
2
虽然很遗憾,但这是将js日期格式化为字符串的最简单方法。我在js方面还很新手,但在Java中,将日期格式化为任何格式要容易100倍。这就是为什么我一直认为有更简单的方法,但在尝试了不同的解决方案后,我选择了这个。感谢您的回答。 - Юрий Яхница
显示剩余6条评论

88

一些答案的组合:

var d = new Date(date);
date = [
  d.getFullYear(),
  ('0' + (d.getMonth() + 1)).slice(-2),
  ('0' + d.getDate()).slice(-2)
].join('-');

3
我最喜欢的解决方案是易于阅读,并且不依赖于 toISOString() 函数及其可能与时区相关的问题。 - mfcallahan
24
这是第一个不让我感到脑疼的。 - ckapilla
如果日期字符串已经处于预期的输出格式且本地时区在UTC以西,则此方法在Chrome中会失败:d = new Date('2022-05-18') 的结果为 '2022-05-17'。这意味着,如果用户的语言环境格式不是 '5/18/2022',那么这个方法也可能会出错。 - mikeypie
1
@mikeypie 不对。你只是简单地错误解析了日期,因为new Date('2022-05-18')将被解析为UTC日期2022-05-18T00:00:00.000Z,如果你在UTC西边,这只是对应于本地时间2022-05-17 - emkey08

63
format = function date2str(x, y) {
    var z = {
        M: x.getMonth() + 1,
        d: x.getDate(),
        h: x.getHours(),
        m: x.getMinutes(),
        s: x.getSeconds()
    };
    y = y.replace(/(M+|d+|h+|m+|s+)/g, function(v) {
        return ((v.length > 1 ? "0" : "") + z[v.slice(-1)]).slice(-2)
    });

    return y.replace(/(y+)/g, function(v) {
        return x.getFullYear().toString().slice(-v.length)
    });
}

结果:

format(new Date('Sun May 11,2014'), 'yyyy-MM-dd')
"2014-05-11

3
我喜欢这个解决方案相较于其他答案提供的额外灵活性。尽管我没有进行全面测试,但对于我所需的格式(即 "yyyy-MM-dd hh:mm:ss"),它的运行效果正如预期。 - porcus
8
您可以轻松避免使用 eval - Salman A
4
以下是避免使用 eval() 函数且更好地注释的版本: https://jsfiddle.net/8904cmLd/2/ - m1m1k
4
我从这个回答中受益了。我已经用“eval”语句替换了那一行,变成了return ((v.length > 1 ? "0" : "") + z[v.slice(-1)]).slice(-2); - JesusIsMyDriver.dll
"H" 应该大写,而不是小写的 "h"。 - DavidDunham

59

如果您不反对使用库,您可以使用Moments.js库,方法如下:

var now = new Date();
var dateString = moment(now).format('YYYY-MM-DD');

var dateStringWithTime = moment(now).format('YYYY-MM-DD HH:mm:ss');
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>


4
很棒的解决方案,但它是一个300kb的软件包。 - Adam
应用于React项目:npm install moment --saveimport moment from 'moment';const showEventDate = moment(your-date-here).format('YYYY-MM-DD; HH:mm A');这是一个在任何格式下呈现日期/时间的纯解决方案。它使用本地日期时间显示上午/下午,并且只需更改格式即可获得所需的任何内容。 [Moment.js](https://momentjs.com/)还提供了简单的日期/时间计数解决方案。 - TradeCoder
@theTradeCoder,正如Adam上面提到的那样,moment的大小相当大(我认为它更像是67kb,但仍然很大),因此在评估任何依赖项的易用性和实用性时,您应该考虑到这一点。还有一些更小的替代品(day.js = 2kb)。 - Tim Hobbs
14
关于 moment.js 库的最新消息,moment.js 已经停止更新。要求将其翻译成通俗易懂的中文,不改变原意。 - Rafik Farhad

51

你可以在 Date 对象上使用 toLocaleDateString('fr-CA')

console.log(new Date('Sun May 11,2014').toLocaleDateString('fr-CA'));

我发现这些语言环境从所有语言环境及其短代码列表中给出了正确的结果。

'en-CA'
'fr-CA'
'lt-LT'
'sv-FI'
'sv-SE'

var localesList = ["af-ZA",
  "am-ET",
  "ar-AE",
  "ar-BH",
  "ar-DZ",
  "ar-EG",
  "ar-IQ",
  "ar-JO",
  "ar-KW",
  "ar-LB",
  "ar-LY",
  "ar-MA",
  "arn-CL",
  "ar-OM",
  "ar-QA",
  "ar-SA",
  "ar-SY",
  "ar-TN",
  "ar-YE",
  "as-IN",
  "az-Cyrl-AZ",
  "az-Latn-AZ",
  "ba-RU",
  "be-BY",
  "bg-BG",
  "bn-BD",
  "bn-IN",
  "bo-CN",
  "br-FR",
  "bs-Cyrl-BA",
  "bs-Latn-BA",
  "ca-ES",
  "co-FR",
  "cs-CZ",
  "cy-GB",
  "da-DK",
  "de-AT",
  "de-CH",
  "de-DE",
  "de-LI",
  "de-LU",
  "dsb-DE",
  "dv-MV",
  "el-GR",
  "en-029",
  "en-AU",
  "en-BZ",
  "en-CA",
  "en-GB",
  "en-IE",
  "en-IN",
  "en-JM",
  "en-MY",
  "en-NZ",
  "en-PH",
  "en-SG",
  "en-TT",
  "en-US",
  "en-ZA",
  "en-ZW",
  "es-AR",
  "es-BO",
  "es-CL",
  "es-CO",
  "es-CR",
  "es-DO",
  "es-EC",
  "es-ES",
  "es-GT",
  "es-HN",
  "es-MX",
  "es-NI",
  "es-PA",
  "es-PE",
  "es-PR",
  "es-PY",
  "es-SV",
  "es-US",
  "es-UY",
  "es-VE",
  "et-EE",
  "eu-ES",
  "fa-IR",
  "fi-FI",
  "fil-PH",
  "fo-FO",
  "fr-BE",
  "fr-CA",
  "fr-CH",
  "fr-FR",
  "fr-LU",
  "fr-MC",
  "fy-NL",
  "ga-IE",
  "gd-GB",
  "gl-ES",
  "gsw-FR",
  "gu-IN",
  "ha-Latn-NG",
  "he-IL",
  "hi-IN",
  "hr-BA",
  "hr-HR",
  "hsb-DE",
  "hu-HU",
  "hy-AM",
  "id-ID",
  "ig-NG",
  "ii-CN",
  "is-IS",
  "it-CH",
  "it-IT",
  "iu-Cans-CA",
  "iu-Latn-CA",
  "ja-JP",
  "ka-GE",
  "kk-KZ",
  "kl-GL",
  "km-KH",
  "kn-IN",
  "kok-IN",
  "ko-KR",
  "ky-KG",
  "lb-LU",
  "lo-LA",
  "lt-LT",
  "lv-LV",
  "mi-NZ",
  "mk-MK",
  "ml-IN",
  "mn-MN",
  "mn-Mong-CN",
  "moh-CA",
  "mr-IN",
  "ms-BN",
  "ms-MY",
  "mt-MT",
  "nb-NO",
  "ne-NP",
  "nl-BE",
  "nl-NL",
  "nn-NO",
  "nso-ZA",
  "oc-FR",
  "or-IN",
  "pa-IN",
  "pl-PL",
  "prs-AF",
  "ps-AF",
  "pt-BR",
  "pt-PT",
  "qut-GT",
  "quz-BO",
  "quz-EC",
  "quz-PE",
  "rm-CH",
  "ro-RO",
  "ru-RU",
  "rw-RW",
  "sah-RU",
  "sa-IN",
  "se-FI",
  "se-NO",
  "se-SE",
  "si-LK",
  "sk-SK",
  "sl-SI",
  "sma-NO",
  "sma-SE",
  "smj-NO",
  "smj-SE",
  "smn-FI",
  "sms-FI",
  "sq-AL",
  "sr-Cyrl-BA",
  "sr-Cyrl-CS",
  "sr-Cyrl-ME",
  "sr-Cyrl-RS",
  "sr-Latn-BA",
  "sr-Latn-CS",
  "sr-Latn-ME",
  "sr-Latn-RS",
  "sv-FI",
  "sv-SE",
  "sw-KE",
  "syr-SY",
  "ta-IN",
  "te-IN",
  "tg-Cyrl-TJ",
  "th-TH",
  "tk-TM",
  "tn-ZA",
  "tr-TR",
  "tt-RU",
  "tzm-Latn-DZ",
  "ug-CN",
  "uk-UA",
  "ur-PK",
  "uz-Cyrl-UZ",
  "uz-Latn-UZ",
  "vi-VN",
  "wo-SN",
  "xh-ZA",
  "yo-NG",
  "zh-CN",
  "zh-HK",
  "zh-MO",
  "zh-SG",
  "zh-TW",
  "zu-ZA"
];

localesList.forEach(lcl => {
  if ("2014-05-11" === new Date('Sun May 11,2014').toLocaleDateString(lcl)) {
    console.log(lcl, new Date('Sun May 11,2014').toLocaleDateString(lcl));
  }
});


有任何想法为什么这个有效吗?ISO格式只是默认值,还是这些语言环境真的使用该格式?如果是前者,我会担心它未来可能会意外更改。 - jymbob
这段代码在浏览器外部的NodeJS中无法运行。 - Daniel Viglione
2
@jymbob 我认为这些地区真的使用这些格式。我通过查看这个维基百科页面得出了相同的答案:https://en.wikipedia.org/wiki/Date_format_by_country - Ciprian Tomoiagă
经过三天的时间,翻阅了太多关于JavaScript日期的SO问题,并尝试在关闭前30分钟提出新问题(被认为是重复的),终于找到了一个真正正确的答案。我简直可以哭出来了。 - Chris F Carroll
感谢这些代码,这确实是在JS渲染中获取格式的更好捷径。 - Ansh Varun
en-CA 在新版 Chrome 中已经无法使用。 - A. Rokinsky

27

使用 Intl 的 2021 解决方案。

新的 Intl 对象现在支持所有浏览器。
您可以通过选择使用所需格式的“区域设置”来选择格式。

瑞典地区设置使用格式“yyyy-mm-dd”:

// Create a date
const date = new Date(2021, 10, 28);

// Create a formatter using the "sv-SE" locale
const dateFormatter = Intl.DateTimeFormat('sv-SE');

// Use the formatter to format the date
console.log(dateFormatter.format(date)); // "2021-11-28"

使用Intl的缺点:

  • 您无法使用此方法“取消格式化”或“解析”字符串
  • 您必须搜索所需的格式(例如在维基百科上),不能使用格式字符串,如“yyyy-mm-dd”

但时间在哪里? - No Idea For Name
这个问题只涉及日期格式。这个答案只返回一个格式化的日期,没有时间。 如果你想格式化时间,请看看其他答案是否能帮到你。 - Hendrik Jan

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