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

60

请求一行格式 - 不使用任何库和 Date 方法,只用正则表达式:

var d = (new Date()).toString().replace(/\S+\s(\S+)\s(\d+)\s(\d+)\s.*/,'$2-$1-$3');
// date will be formatted as "14-Oct-2015" (pass any date object in place of 'new Date()')

在我的测试中,这在主要的浏览器(Chrome、Safari、Firefox和IE)中可以可靠地工作。正如@RobG所指出的那样,Date.prototype.toString() 的输出取决于实现,因此对于国际化或非浏览器实现,只需测试输出以确保它在您的JavaScript引擎中正常工作即可。您甚至可以添加一些代码来测试字符串输出并确保它与您期望的匹配,然后再进行正则表达式替换。


55

打包解决方案: Luxondate-fns

如果您想使用一个适合所有情况的解决方案,我建议使用date-fns或Luxon。

Luxon在Moment.js网站上托管,并由一个Moment.js开发者开发,因为Moment.js有一些限制,而开发者想要解决这些问题但又无法做到。

安装方法:

npm install luxonyarn add luxon (访问链接查看其他安装方法)

示例:

luxon.DateTime.fromISO('2010-08-10').toFormat('yyyy-LLL-dd');

结果为:

10-Aug-2010

手动解决方案

使用与Moment.js类似的格式,Class DateTimeFormatter(Java),以及Class SimpleDateFormat(Java),我实现了一个综合解决方案formatDate(date,patternStr),其中代码易于阅读和修改。您可以显示日期、时间、AM/PM等。有关更多示例,请参见代码。

示例:

formatDate(new Date(),'EEEE, MMMM d, yyyy HH:mm:ss:S')

formatDate在下面的代码段中实现)

结果为:

Friday, October 12, 2018 18:11:23:445

点击“运行代码片段”尝试代码。

日期和时间格式

yy = 2位数年份; yyyy = 完整年份

M = 数字月份; MM = 2位数字月份; MMM = 短月份名称; MMMM = 全月份名称

EEEE = 全星期名称; EEE = 短星期名称

d = 数字日期; dd = 2位数字日期

h = 上下午小时; hh = 2位上下午小时; H = 小时; HH = 2位小时

m = 分钟; mm = 2位数字分钟; aaa = 上午/下午

s代表秒;ss代表两位数的秒。

S代表毫秒。

var monthNames = [
  "January", "February", "March", "April", "May", "June", "July",
  "August", "September", "October", "November", "December"
];
var dayOfWeekNames = [
  "Sunday", "Monday", "Tuesday",
  "Wednesday", "Thursday", "Friday", "Saturday"
];
function formatDate(date, patternStr){
    if (!patternStr) {
        patternStr = 'M/d/yyyy';
    }
    var day = date.getDate(),
        month = date.getMonth(),
        year = date.getFullYear(),
        hour = date.getHours(),
        minute = date.getMinutes(),
        second = date.getSeconds(),
        miliseconds = date.getMilliseconds(),
        h = hour % 12,
        hh = twoDigitPad(h),
        HH = twoDigitPad(hour),
        mm = twoDigitPad(minute),
        ss = twoDigitPad(second),
        aaa = hour < 12 ? 'AM' : 'PM',
        EEEE = dayOfWeekNames[date.getDay()],
        EEE = EEEE.substr(0, 3),
        dd = twoDigitPad(day),
        M = month + 1,
        MM = twoDigitPad(M),
        MMMM = monthNames[month],
        MMM = MMMM.substr(0, 3),
        yyyy = year + "",
        yy = yyyy.substr(2, 2)
    ;
    // checks to see if month name will be used
    patternStr = patternStr
      .replace('hh', hh).replace('h', h)
      .replace('HH', HH).replace('H', hour)
      .replace('mm', mm).replace('m', minute)
      .replace('ss', ss).replace('s', second)
      .replace('S', miliseconds)
      .replace('dd', dd).replace('d', day)
      
      .replace('EEEE', EEEE).replace('EEE', EEE)
      .replace('yyyy', yyyy)
      .replace('yy', yy)
      .replace('aaa', aaa);
    if (patternStr.indexOf('MMM') > -1) {
        patternStr = patternStr
          .replace('MMMM', MMMM)
          .replace('MMM', MMM);
    }
    else {
        patternStr = patternStr
          .replace('MM', MM)
          .replace('M', M);
    }
    return patternStr;
}
function twoDigitPad(num) {
    return num < 10 ? "0" + num : num;
}
console.log(formatDate(new Date()));
console.log(formatDate(new Date(), 'dd-MMM-yyyy')); //OP's request
console.log(formatDate(new Date(), 'EEEE, MMMM d, yyyy HH:mm:ss.S aaa'));
console.log(formatDate(new Date(), 'EEE, MMM d, yyyy HH:mm'));
console.log(formatDate(new Date(), 'yyyy-MM-dd HH:mm:ss.S'));
console.log(formatDate(new Date(), 'M/dd/yyyy h:mmaaa'));

感谢 @Gerry 提及 Luxon。


是的,Moment已经被弃用了。请使用Luxon。 - TamusJRoyce

50

@Sébastien -- 全浏览器支持的替代方案

new Date(parseInt(496407600)*1000).toLocaleDateString('de-DE', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
}).replace(/\./g, '/');

文档: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString


基于 Date.toLocaleDateString 的高级标签模板文字示例:

const date = new Date(Date.UTC(2020, 4, 2, 3, 23, 16, 738));
const fmt = (dt, lc = "en-US") => (str, ...expr) =>
    str.map((str, i) => str + (expr[i]?dt.toLocaleDateString(lc, expr[i]) :'')).join('')

console.log(fmt(date)`${{year: 'numeric'}}-${{month: '2-digit'}}-${{day: '2-digit'}}`);
// expected output: "2020-05-02"

5
你可以直接使用'en-GB'作为语言环境,而不是使用.replace()方法。 :) - Roberto14

43

好的,我们有一个被称为Intl的东西,这在JavaScript中格式化日期非常实用:

您的日期如下:

var date = '10/8/2010';

使用 new Date() 可以将其转换为日期,例如:

date = new Date(date);

现在,您可以使用以下区域设置列表以任何想要的方式对其进行格式化:

date = new Intl.DateTimeFormat('en-AU').format(date); // Australian date format: "8/10/2010" 


:空段落。
date = new Intl.DateTimeFormat('en-US').format(date); // USA date format: "10/8/2010" 


->


date = new Intl.DateTimeFormat('ar-EG').format(date);  // Arabic date format: "٨‏/١٠‏/٢٠١٠"

如果你确切地想要上述提到的格式,你可以这样做:

date = new Date(Date.UTC(2010, 7, 10, 0, 0, 0));
var options = {year: "numeric", month: "short", day: "numeric"};
date = new Intl.DateTimeFormat("en-AU", options).format(date).replace(/\s/g, '-');

结果将会是:

"10-Aug-2010"

更多信息请参阅 Intl APIIntl.DateTimeFormat 文档。


不支持IE浏览器。 - Pants
1
仅适用于IE11,IE10-早在此之前就退出了生命周期,因此可以理解。来自caniuse的92%,非常不错https://caniuse.com/#search=datetimeformat - Tofandel

36

使用 ECMAScript 第六版(ES6/ES2015)的字符串模板:

let d = new Date();
let formatted = `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`;

如果您需要更改分隔符:

const delimiter = '/';
let formatted = [d.getFullYear(), d.getMonth() + 1, d.getDate()].join(delimiter);

36

Date 构造函数(以及 Date.parse())在构造日期时只接受一个格式作为参数,那就是ISO 8601

// new Date('YYYY-MM-DDTHH:mm:ss.sssZ')
const date = new Date('2017-08-15')

但是,从字符串中解析日期被强烈不建议(MDN建议不要使用日期字符串创建日期),因为不同浏览器之间存在差异和不一致性。

推荐的替代方法是直接从数字数据构建您的Date实例,如下所示:

new Date(2017, 7, 15) // Month is zero-indexed

那就是解析。现在,要将您的日期格式化为所需的字符串,您有几个选项是Date对象本身提供的(尽管我认为没有一个与您需要的格式兼容):

date.toString()       // 'Wed Jan 23 2019 17:23:42 GMT+0800 (Singapore Standard Time)'
date.toDateString()   // 'Wed Jan 23 2019'
date.toLocaleString() // '23/01/2019, 17:23:42'
date.toGMTString()    // 'Wed, 23 Jan 2019 09:23:42 GMT'
date.toUTCString()    // 'Wed, 23 Jan 2019 09:23:42 GMT'
date.toISOString()    // '2019-01-23T09:23:42.079Z'

对于其他的格式选项,恐怕您需要求助于类似 Moment.jsday.js 等库。

感谢来自这篇文章Zell Liew提供的日期格式化技巧。


25

这是我刚刚为我正在开发的项目编写的一些代码,用于处理日期格式。它模仿了PHP日期格式化功能以满足我的需求。随意使用它,它只是扩展了已经存在的Date()对象。这可能不是最优雅的解决方案,但它对我的需求有效。

var d = new Date(); 
d_string = d.format("m/d/Y h:i:s");

/**************************************
 * Date class extension
 * 
 */
    // Provide month names
    Date.prototype.getMonthName = function(){
        var month_names = [
                            'January',
                            'February',
                            'March',
                            'April',
                            'May',
                            'June',
                            'July',
                            'August',
                            'September',
                            'October',
                            'November',
                            'December'
                        ];

        return month_names[this.getMonth()];
    }

    // Provide month abbreviation
    Date.prototype.getMonthAbbr = function(){
        var month_abbrs = [
                            'Jan',
                            'Feb',
                            'Mar',
                            'Apr',
                            'May',
                            'Jun',
                            'Jul',
                            'Aug',
                            'Sep',
                            'Oct',
                            'Nov',
                            'Dec'
                        ];

        return month_abbrs[this.getMonth()];
    }

    // Provide full day of week name
    Date.prototype.getDayFull = function(){
        var days_full = [
                            'Sunday',
                            'Monday',
                            'Tuesday',
                            'Wednesday',
                            'Thursday',
                            'Friday',
                            'Saturday'
                        ];
        return days_full[this.getDay()];
    };

    // Provide full day of week name
    Date.prototype.getDayAbbr = function(){
        var days_abbr = [
                            'Sun',
                            'Mon',
                            'Tue',
                            'Wed',
                            'Thur',
                            'Fri',
                            'Sat'
                        ];
        return days_abbr[this.getDay()];
    };

    // Provide the day of year 1-365
    Date.prototype.getDayOfYear = function() {
        var onejan = new Date(this.getFullYear(),0,1);
        return Math.ceil((this - onejan) / 86400000);
    };

    // Provide the day suffix (st,nd,rd,th)
    Date.prototype.getDaySuffix = function() {
        var d = this.getDate();
        var sfx = ["th","st","nd","rd"];
        var val = d%100;

        return (sfx[(val-20)%10] || sfx[val] || sfx[0]);
    };

    // Provide Week of Year
    Date.prototype.getWeekOfYear = function() {
        var onejan = new Date(this.getFullYear(),0,1);
        return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7);
    } 

    // Provide if it is a leap year or not
    Date.prototype.isLeapYear = function(){
        var yr = this.getFullYear();

        if ((parseInt(yr)%4) == 0){
            if (parseInt(yr)%100 == 0){
                if (parseInt(yr)%400 != 0){
                    return false;
                }
                if (parseInt(yr)%400 == 0){
                    return true;
                }
            }
            if (parseInt(yr)%100 != 0){
                return true;
            }
        }
        if ((parseInt(yr)%4) != 0){
            return false;
        } 
    };

    // Provide Number of Days in a given month
    Date.prototype.getMonthDayCount = function() {
        var month_day_counts = [
                                    31,
                                    this.isLeapYear() ? 29 : 28,
                                    31,
                                    30,
                                    31,
                                    30,
                                    31,
                                    31,
                                    30,
                                    31,
                                    30,
                                    31
                                ];

        return month_day_counts[this.getMonth()];
    } 

    // format provided date into this.format format
    Date.prototype.format = function(dateFormat){
        // break apart format string into array of characters
        dateFormat = dateFormat.split("");

        var date = this.getDate(),
            month = this.getMonth(),
            hours = this.getHours(),
            minutes = this.getMinutes(),
            seconds = this.getSeconds();
        // get all date properties ( based on PHP date object functionality )
        var date_props = {
            d: date < 10 ? '0'+date : date,
            D: this.getDayAbbr(),
            j: this.getDate(),
            l: this.getDayFull(),
            S: this.getDaySuffix(),
            w: this.getDay(),
            z: this.getDayOfYear(),
            W: this.getWeekOfYear(),
            F: this.getMonthName(),
            m: month < 10 ? '0'+(month+1) : month+1,
            M: this.getMonthAbbr(),
            n: month+1,
            t: this.getMonthDayCount(),
            L: this.isLeapYear() ? '1' : '0',
            Y: this.getFullYear(),
            y: this.getFullYear()+''.substring(2,4),
            a: hours > 12 ? 'pm' : 'am',
            A: hours > 12 ? 'PM' : 'AM',
            g: hours % 12 > 0 ? hours % 12 : 12,
            G: hours > 0 ? hours : "12",
            h: hours % 12 > 0 ? hours % 12 : 12,
            H: hours,
            i: minutes < 10 ? '0' + minutes : minutes,
            s: seconds < 10 ? '0' + seconds : seconds           
        };

        // loop through format array of characters and add matching data else add the format character (:,/, etc.)
        var date_string = "";
        for(var i=0;i<dateFormat.length;i++){
            var f = dateFormat[i];
            if(f.match(/[a-zA-Z]/g)){
                date_string += date_props[f] ? date_props[f] : '';
            } else {
                date_string += f;
            }
        }

        return date_string;
    };
/*
 *
 * END - Date class extension
 * 
 ************************************/

23

这可能有助于解决问题:

var d = new Date();

var options = {   
    day: 'numeric',
    month: 'long', 
    year: 'numeric'
};

console.log(d.toLocaleDateString('en-ZA', options));


20

不使用任何外部库的JavaScript解决方案:

var now = new Date()
months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
var formattedDate = now.getDate() + "-" + months[now.getMonth()] + "-" + now.getFullYear()
alert(formattedDate)

20

在JavaScript中格式化日期时间的一种有用且灵活的方式是使用Intl.DateTimeFormat

var date = new Date();
var options = { year: 'numeric', month: 'short', day: '2-digit'};
var _resultDate = new Intl.DateTimeFormat('en-GB', options).format(date);
// The _resultDate is: "12 Oct 2017"
// Replace all spaces with - and then log it.
console.log(_resultDate.replace(/ /g,'-'));

结果是:"12-Oct-2017"

可以使用选项参数自定义日期和时间格式。

Intl.DateTimeFormat 对象是一个构造函数,用于创建启用语言敏感的日期和时间格式化的对象。

语法

new Intl.DateTimeFormat([locales[, options]])
Intl.DateTimeFormat.call(this[, locales[, options]])

参数

locales

可选。一个BCP 47语言标签的字符串,或者这样的字符串数组。关于locales参数的一般形式和解释,请参见Intl页面。以下Unicode扩展键是允许的:

nu
Numbering system. Possible values include: "arab", "arabext", "bali", "beng", "deva", "fullwide", "gujr", "guru", "hanidec", "khmr", "knda", "laoo", "latn", "limb", "mlym", "mong", "mymr", "orya", "tamldec", "telu", "thai", "tibt".
ca
Calendar. Possible values include: "buddhist", "chinese", "coptic", "ethioaa", "ethiopic", "gregory", "hebrew", "indian", "islamic", "islamicc", "iso8601", "japanese", "persian", "roc".

选项

可选。一个对象,包含以下一些或全部属性:

localeMatcher

要使用的区域匹配算法。可能的值为"lookup""best fit";默认值为"best fit"。有关此选项的信息,请参见Intl页面。

timeZone

要使用的时区。实现必须识别的唯一值是"UTC";默认值为运行时的默认时区。实现还可以识别IANA时区数据库的时区名称,例如"Asia/Shanghai""Asia/Kolkata""America/New_York"等。

hour12

是否使用12小时制(而不是24小时制)。可能的值为truefalse;默认值取决于区域设置。

formatMatcher

要使用的格式匹配算法。可能的值为"basic""best fit";默认值为"best fit"。有关此属性的使用信息,请参见下面的段落。

以下属性描述了要在格式化输出中使用的日期时间组件及其所需的表示方式。实现至少需要支持以下子集:

weekday, year, month, day, hour, minute, second
weekday, year, month, day
year, month, day
year, month
month, day
hour, minute, second
hour, minute

实现可能支持其他子集,请求将针对所有可用的子集表示组合进行协商以找到最佳匹配。两种算法可用于此协商,并由formatMatcher属性选择:一个完全指定的"basic"算法和一个实现相关的"best fit"算法。

weekday

星期的表示方式。可能的值为"narrow""short""long"

era

纪元的表示方式。可能的值为"narrow""short""long"

year

年份的表示方式。可能的值为"numeric""2-digit"

month

月份的表示方式。可能的值为"numeric""2-digit""narrow""short""long"

day

日期的表示方式。可能的值为"numeric""2-digit"

hour

小时的表示方式。可能的值为"numeric""2-digit"

minute

分钟的表示方式。可能的值为"numeric""2-digit"

second

秒数的表示方式。可能的值为"numeric""2-digit"

timeZoneName

时区名称的表示方式。可能的值为"short""long"。每个日期时间组件属性的默认值为undefined,但如果所有组件属性都是undefined,则假定年份、月份和日期为"numeric"

在线查看

更多详情


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