如何在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个回答

18

16

我们有很多解决方案,但我认为其中最好的是Moment.js。因此,我个人建议在日期和时间操作中使用Moment.js。

console.log(moment().format('DD-MMM-YYYY'));
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>


15

这是我为我的npm插件实现的方式

var monthNames = [
  "January", "February", "March",
  "April", "May", "June", "July",
  "August", "September", "October",
  "November", "December"
];

var Days = [
  "Sunday", "Monday", "Tuesday", "Wednesday",
  "Thursday", "Friday", "Saturday"
];

var formatDate = function(dt,format){
  format = format.replace('ss', pad(dt.getSeconds(),2));
  format = format.replace('s', dt.getSeconds());
  format = format.replace('dd', pad(dt.getDate(),2));
  format = format.replace('d', dt.getDate());
  format = format.replace('mm', pad(dt.getMinutes(),2));
  format = format.replace('m', dt.getMinutes());
  format = format.replace('MMMM', monthNames[dt.getMonth()]);
  format = format.replace('MMM', monthNames[dt.getMonth()].substring(0,3));
  format = format.replace('MM', pad(dt.getMonth()+1,2));
  format = format.replace(/M(?![ao])/, dt.getMonth()+1);
  format = format.replace('DD', Days[dt.getDay()]);
  format = format.replace(/D(?!e)/, Days[dt.getDay()].substring(0,3));
  format = format.replace('yyyy', dt.getFullYear());
  format = format.replace('YYYY', dt.getFullYear());
  format = format.replace('yy', (dt.getFullYear()+"").substring(2));
  format = format.replace('YY', (dt.getFullYear()+"").substring(2));
  format = format.replace('HH', pad(dt.getHours(),2));
  format = format.replace('H', dt.getHours());
  return format;
}

pad = function(n, width, z) {
  z = z || '0';
  n = n + '';
  return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}

你指的是哪个包? - lbrahim
这里有一个bug:月份名称会先被替换,然后月份的名称也会被替换。例如,使用这段代码,“March”将变成“3arch”。 - ntaso
1
'M'的行更改为format = format.replace("M(?!M)", (dt.getMonth()+1).toString());,并将其放在带有'MMMM'的行上方。 - ntaso
这个示例的演示可以在这里找到:https://jsfiddle.net/Abeeee/Ly8v3s0x/24/ - user1432181

15
如果您的代码中使用了jQuery UI,那么有一个内置函数叫做formatDate()。我是这样使用它来格式化今天的日期的:
var testdate = Date();
testdate = $.datepicker.formatDate( "d-M-yy",new Date(testdate));
alert(testdate);

您可以在jQuery UI文档中看到许多其他格式化日期的示例


14
你应该看一下DayJs。这是momentJs的一个重制版,采用模块化架构,更加轻便。 快速、2KB小的Moment.js替代品,具有相同的现代API。

Day.js是一个极简的JavaScript库,支持解析、验证、操作和显示日期和时间,并提供一个与Moment.js兼容的API,适用于现代浏览器。如果您使用Moment.js,那么您已经知道如何使用Day.js了。

var date = Date.now();
const formatedDate = dayjs(date).format("YYYY-MM-DD")
console.log(formatedDate);
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.8.16/dayjs.min.js" crossorigin="anonymous"></script>


13

Typescript版本

可以轻松地增强以支持所需的任何格式字符串。当像这样的通用解决方案如此容易创建,并且日期格式化在应用程序中经常出现时,我不建议在整个应用程序中硬编码日期格式代码。它更难阅读并隐藏了您的意图。格式字符串清楚地显示您的意图。

原型函数

interface Date {
    format(formatString: string): string;
}

Date.prototype.format = function (formatString: string): string {
  return Object.entries({
    YYYY: this.getFullYear(),
    YY: this.getFullYear().toString().substring(2),
    yyyy: this.getFullYear(),
    yy: this.getFullYear().toString().substring(2),
    MMMM: this.toLocaleString('default', { month: 'long' }),
    MMM: this.toLocaleString('default', { month: 'short' }),
    MM: (this.getMonth() + 1).toString().padStart(2, '0'),
    M: this.getMonth() + 1,
    DDDD: this.toLocaleDateString('default', { weekday: 'long' }),
    DDD: this.toLocaleDateString('default', { weekday: 'short' }),
    DD: this.getDate().toString().padStart(2, '0'),
    D: this.getDate(),
    dddd: this.toLocaleDateString('default', { weekday: 'long' }),
    ddd: this.toLocaleDateString('default', { weekday: 'short' }),
    dd: this.getDate().toString().padStart(2, '0'),
    d: this.getDate(),
    HH: this.getHours().toString().padStart(2, '0'), // military
    H: this.getHours().toString(), // military
    hh: (this.getHours() % 12).toString().padStart(2, '0'),
    h: (this.getHours() % 12).toString(),
    mm: this.getMinutes().toString().padStart(2, '0'),
    m: this.getMinutes(),
    SS: this.getSeconds().toString().padStart(2, '0'),
    S: this.getSeconds(),
    ss: this.getSeconds().toString().padStart(2, '0'),
    s: this.getSeconds(),
    TTT: this.getMilliseconds().toString().padStart(3, '0'),
    ttt: this.getMilliseconds().toString().padStart(3, '0'),
    AMPM: this.getHours() < 13 ? 'AM' : 'PM',
    ampm: this.getHours() < 13 ? 'am' : 'pm',
  }).reduce((acc, entry) => {
    return acc.replace(entry[0], entry[1].toString())
  }, formatString)
}

演示

function unitTest() {
    var d: Date = new Date()
    console.log(d.format('MM/dd/yyyy hh:mm:ss')) // 12/14/2022 03:38:31
    console.log(d.format('yyyy-MM-dd HH:mm:ss')) // 2022-12-14 15:38:31
}

unitTest()

Javascript版本

与之前相同,只需删除接口以及冒号后面的类型名称及其相关冒号。

片段

Date.prototype.format = function(formatString) {
  return Object.entries({
    YYYY: this.getFullYear(),
    YY: this.getFullYear().toString().substring(2),
    yyyy: this.getFullYear(),
    yy: this.getFullYear().toString().substring(2),
    MMMM: this.toLocaleString('default', { month: 'long'  }),
    MMM: this.toLocaleString('default',  { month: 'short' }),
    MM: (this.getMonth() + 1).toString().padStart(2, '0'),
    M: this.getMonth() + 1,
    DDDD: this.toLocaleDateString('default', { weekday: 'long'  }),
    DDD: this.toLocaleDateString('default',  { weekday: 'short' }),
    DD: this.getDate().toString().padStart(2, '0'),
    D: this.getDate(),
    dddd: this.toLocaleDateString('default', { weekday: 'long'  }),
    ddd: this.toLocaleDateString('default',  { weekday: 'short' }),
    dd: this.getDate().toString().padStart(2, '0'),
    d: this.getDate(),
    HH: this.getHours().toString().padStart(2, '0'), // military
    H: this.getHours().toString(), // military
    hh: (this.getHours() % 12).toString().padStart(2, '0'),
    h: (this.getHours() % 12).toString(),
    mm: this.getMinutes().toString().padStart(2, '0'),
    m: this.getMinutes(),
    SS: this.getSeconds().toString().padStart(2, '0'),
    S: this.getSeconds(),
    ss: this.getSeconds().toString().padStart(2, '0'),
    s: this.getSeconds(),
    TTT: this.getMilliseconds().toString().padStart(3, '0'),
    ttt: this.getMilliseconds().toString().padStart(3, '0'),
    AMPM: this.getHours() < 13 ? 'AM' : 'PM',
    ampm: this.getHours() < 13 ? 'am' : 'pm',
  }).reduce((acc, entry) => {
    return acc.replace(entry[0], entry[1].toString())
  }, formatString)
}



function unitTest() {
  var d = new Date()
  console.log(d.format('MM/dd/yyyy hh:mm:ss')) // 12/14/2022 03:38:31
  console.log(d.format('yyyy-MM-dd HH:mm:ss')) // 2022-12-14 15:38:31
}

unitTest()


不要重复造轮子,使用可靠稳定的库,如 moment 库,是一个好主意。 - Willian
@Willian,我不知道,这个代码完美运行而且比moment小得多。请告诉我它在哪里不可靠或不稳定。另外,你是否也评论了这些更丑陋、更复杂的答案? - toddmo
3
@Willian,moment 正在经历一个时刻,在此时刻。如果我不指出 moment 已经过时了,那就太不友善了。因此,请找到另一个更小的库,它不会停止更新,并支持模块化导入。Github 的自述文件说明它已经过时了,你应该选择另一个库。你的研究已经落后了。所以,在你找到最好的替代品之后,再用更有力的论据来反驳使用库和自己编写代码的优劣。 - toddmo
1
这是一种反模式。不要修改您没有所有权的对象 (在这种情况下,指的是Date原型)。 - jens1101
2
ењЁJavaScriptдё­жІЎжњ‰formatгЂ‚ - jebbie
显示剩余4条评论

12
var today = new Date();
var formattedToday = today.toLocaleDateString() + ' ' + today.toLocaleTimeString();

12

JD Smith精彩的正则表达式解决方案启发,我突然有了这个令人头疼的想法:

var D = Date().toString().split(" ");
console.log(D[2] + "-" + D[1] + "-" + D[3]);


1
如果你需要在DOM中直接使用它,这是一个不错的变化! - JD Smith

10

Internet Explorer 11、Firefox和Chrome(选择en-UK时,Chrome 80.x显示12小时格式)中都是相同的。

const d = new Date('2010/08/05 23:45') // 26.3.2020
const dtfUK = new Intl.DateTimeFormat('UK', { year: 'numeric', month: '2-digit', day: '2-digit',
        hour: '2-digit',minute: '2-digit', second: '2-digit' }); //
const dtfUS = new Intl.DateTimeFormat('en', { year: 'numeric', month: '2-digit', day: '2-digit',
        hour: '2-digit',minute: '2-digit', second: '2-digit' }); //
console.log(dtfUS.format(d)); // 08/05/2010 11:45:00 PM
console.log(dtfUK.format(d)); // 05.08.2010 23:45:00
/* node.js:
08/05/2010, 11:45:00 PM
2010-08-05 23:45:00
*/

还有一些更普遍的东西吗?

var d = new Date('2010-08-10T10:34:56.789Z');
var str = d.toDateString() + // Tue Aug 10 2010
    ' ' + d.toTimeString().split(' ')[0] + // 12:34:56, GMT+0x00 (GMT+0x:00)
    ' ' + (d.getMonth() + 101) + // 108
    ' ' + d.getMilliseconds(); // 789
console.log(str); // Tue Aug 10 2010 12:34:56 108 789
console.log(//   $1 Tue  $2 Aug  $3 11     $4 2020 $5 12   $6 34   $7 56    $8 108  $9 789
    str.replace(/(\S{3}) (\S{3}) (\d{1,2}) (\d{4}) (\d{2}):(\d{2}):(\d{2}) 1(\d{2}) (\d{1,3})/, '$3-$2-$4 $5:$6.$9 ($1)')
); // 10-Aug-2010 12:34.789 (Tue)
/*
$1: Tue  Week Day string
$2: Aug  Month short text
$3: 11   Day
$4: 2010 Year
$5: 12   Hour
$6: 34   Minute
$7: 56   Seconds
$8: 08   Month
$9: 789  Milliseconds
*/

例如1行IIFE {{立即执行函数}} "库" ;-)

console.log(
    (function (frm, d) { return [d.toDateString(), d.toTimeString().split(' ')[0], (d.getMonth() + 101), d.getMilliseconds()].join(' ').replace(/(\S{3}) (\S{3}) (\d{1,2}) (\d{4}) (\d{2}):(\d{2}):(\d{2}) 1(\d{2}) (\d{1,3})/, frm); })
    ('$4/$8/$3 $5:$6 ($1)', new Date())
);

如果您不需要它们,可以删除无用部分和/或更改索引。


10

简单格式化程序:

function fmt(date, format = 'YYYY-MM-DDThh:mm:ss') {
  const pad2 = (n) => n.toString().padStart(2, '0');

  const map = {
    YYYY: date.getFullYear(),
    MM: pad2(date.getMonth() + 1),
    DD: pad2(date.getDate()),
    hh: pad2(date.getHours()),
    mm: pad2(date.getMinutes()),
    ss: pad2(date.getSeconds()),
  };

  return Object.entries(map).reduce((prev, entry) => prev.replace(...entry), format);
}

// Usage
console.log(
  fmt(new Date(), 'YYYY-MM-DDThh:mm:ss') // '2023-03-04T10:30:24'
);
console.log(
  fmt(new Date(), 'MM/DD/YYYY, hh:mm:ss') // '03/04/2023, 10:30:24'
);


1
很好。非常好。 - mplungjan

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