JavaScript将日期前面加0

616

我创建了这个脚本来计算10天后的日期,格式为dd/mm/yyyy:

var MyDate = new Date();
var MyDateString = new Date();
MyDate.setDate(MyDate.getDate()+10);
MyDateString = MyDate.getDate() + '/' + (MyDate.getMonth()+1) + '/' + MyDate.getFullYear();

我需要在日期的日和月组成部分上添加前导零,通过将这些规则添加到脚本中来实现。但我似乎无法让它起作用。

if (MyDate.getMonth < 10)getMonth = '0' + getMonth;

if (MyDate.getDate <10)get.Date = '0' + getDate;

如果有人能告诉我在脚本中应该插入这些内容的位置,我会非常感激。


7
作为一种良好的惯例,您应该将变量名的第一个字符设置为小写,并将驼峰命名保留给对象/原型。 - zykadelic
如果YYYY-MM-DD格式可接受,这将是一个非常好的答案:https://dev59.com/UXA75IYBdhLWcg3w3NBe#28431880 - Fabien Snauwaert
2
向下滚动以查看ES6+ padStart答案 - technogeek1995
33个回答

1656

试试这个:http://jsfiddle.net/xA5B7/

var MyDate = new Date();
var MyDateString;

MyDate.setDate(MyDate.getDate() + 20);

MyDateString = ('0' + MyDate.getDate()).slice(-2) + '/'
             + ('0' + (MyDate.getMonth()+1)).slice(-2) + '/'
             + MyDate.getFullYear();

编辑:

解释一下,.slice(-2) 给我们提供了字符串的最后两个字符。

所以无论如何,我们都可以将"0"添加到日或月份,并且仅要求最后两个字符,因为这两个字符总是我们需要的。

因此,如果 MyDate.getMonth() 返回 9,则结果是:

("0" + "9") // Giving us "09"

因此,在其上添加.slice(-2)会给我们最后两个字符,即:

("0" + "9").slice(-2)
"09"

但是如果MyDate.getMonth()返回10,那么它将是:

("0" + "10") // Giving us "010"

所以添加 .slice(-2) 将给我们最后两个字符,即:

("0" + "10").slice(-2)
"10"

45
分叉 - 日期格式为YYYY-MM-DD这可能对某些人有用。谢谢 - tomexx
3
有人能解释一下为什么这比@Aleross在下面提供的答案更好吗?它与明确清晰的pad函数相比并不立即清楚它做了什么。 - claudio
2
更不用说今天这个示例给了我 2014年6月26日 而不是 2014年6月6日。 - DazManCat
4
这段代码的作用是将当前日期加上20天。具体实现是通过 MyDate.setDate(MyDate.getDate() + 20); 来完成的。 - cookie monster
3
@n00b 和 @Phil Cooper,不要陷入关于计时 JavaScript 程序的细节讨论中,我发现在100万次迭代中,被接受答案中的 slice() 技术比 @Aleross 的 pad() 技术快大约1/10秒。请自行选择使用。jsFiddle。"花钱,做决定"。 - Karl
显示剩余6条评论

286

现代方式

现代的做法是使用toLocaleDateString,因为它不仅可以使日期格式化本地化,还可以传递格式选项以达到所需的结果:

const date = new Date(2018, 2, 1)
const result = date.toLocaleDateString("en-GB", { // you can use undefined as first argument
  year: "numeric",
  month: "2-digit",
  day: "2-digit",
})
console.log(result) // outputs “01/03/2018”

或者使用一个时间对象(仍在提案中, 可以使用):

const date = new Temporal.PlainDate(2018, 3, 1) // also works with zoned date
const result = date.toLocaleString("en-GB", { // you can use undefined as first argument
  year: "numeric",
  month: "2-digit",
  day: "2-digit",
})
console.log(result) // outputs “01/03/2018”

当您使用undefined作为第一个参数时,它会检测浏览器语言。或者,您也可以在年份选项中使用2-digit
性能方面,如果您打算格式化许多日期,建议使用Intl.DateTimeFormat代替。

const formatter = new Intl.DateTimeFormat("en-GB", { // <- re-use me
  year: "numeric",
  month: "2-digit",
  day: "2-digit",
})
const date = new Date(2018, 2, 1) // can also be a Temporal object
const result = formatter.format(date)
console.log(result) // outputs “01/03/2018”

该格式化程序兼容于日期和时间对象。

历史日期

与Temporal构造函数不同,Date构造函数中0到99年将被解释为20世纪的年份。为了防止这种情况发生,请按以下方式初始化日期:

const date = new Date()
date.setFullYear(18, 2, 1) // the year is A.D. 18

这不是Temporal对象必需的,但在某些情况下,年份低于1000时将不包含前导零,因为格式化程序(该程序用于Date和Temporal API)根本不支持4位数字格式。在这种情况下,您需要进行手动格式化(请参见下文)。
对于ISO 8601格式,如果您想以YYYY-MM-DD格式(ISO 8601)获取日期,则解决方案看起来不同:

const date = new Date(Date.UTC(2018, 2, 1))
const result = date.toISOString().split('T')[0]
console.log(result) // outputs “2018-03-01”

您输入的日期应该采用UTC格式,或者toISOString()可以为您解决此问题。如上所示,使用Date.UTC实现。

ISO 8601格式下的历史日期

与Temporal构造函数不同,在Date构造函数中0到99年将被解释为20世纪的年份。为了避免这种情况,请按以下方式初始化日期以用于ISO 8601格式:

const date = new Date()
date.setUTCFullYear(18, 2, 1) // the year is A.D. 18

请注意,年份在公元1000年之前或公元9999年之后的时间对象的ISO格式与旧版Date API有不同的格式。建议在所有情况下回退到自定义格式以强制使用4位数的年份。

年份的自定义4位数格式

很遗憾,格式化程序不支持年份前导零。没有4-digit选项。这也适用于Temporal对象,因为它们共享相同的格式化程序。
幸运的是,Date API的ISO格式将始终显示至少4个数字的年份,尽管Temporal对象不会。因此,至少对于Date API,您可以通过回退到使用ISO 8601格式方法的一部分的手动格式化方法来格式化1000年之前的历史日期并添加前导零:

const date = new Date()
date.setUTCFullYear(18, 2, 1)
const ymd = date.toISOString().split('T')[0].split('-')
const result = `${ymd[2]}/${ymd[1]}/${ymd[0]}`
console.log(result) // outputs “01/03/0018”

对于时间对象,需要不同的处理方式,因为如前所述,ISOYearString在公元1000年之前和9999年之后的日期格式不同

const date = new Temporal.PlainDate(2018, 3, 1) // also works with zoned date
const zeroPad = (n, digits) => n.toString().padStart(digits, '0');
const result = `${zeroPad(date.day, 2)}/${zeroPad(date.month, 2)}/${zeroPad(date.year, 4)}`;
console.log(result) // outputs “01/03/0018”

杂项

对于日期和时间 API,还有toLocaleTimeString,它允许您本地化并格式化日期的时间。


7
这正是我一直在寻找的,谢谢。更多关于toLocaleDateString可用选项的信息,请参见此处:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString - JoseLinares
1
@JoseLinares 您好,感谢您在过去重新放置此链接。我决定改进我的答案,使解决方案更适用于常见情况,因为您可以跳过第一个参数,而IE10已不再相关。考虑到这一点,我将您的链接包含在我的答案中。 - Martin Braun
@modiX,抱歉,这是我的代码错误,我误解了描述,是的,locales(第一个变量)是可选的 - Kanhaiya lal
如何使用此方法为年份添加前导零? year:“numeric” 会将年份显示为原样,而不是4位数字 :( - Sixteen
1
很遗憾,现代方法中没有4位数格式选项来处理1000年以下的历史日期。我更新了我的答案来解决你的问题,并为这种情况提供了替代方案。虽然我希望有更好的方法来解决这个问题。 - Martin Braun

128

这是来自Mozilla开发者网络上Date对象文档的一个示例,使用了自定义的“pad”函数,而不必扩展Javascript的Number原型。他们提供的方便函数示例如下:

function pad(n){return n<10 ? '0'+n : n}

以下是在上下文中使用它的示例。

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

4
做得非常好。我认为被接受的答案已经很棒了,但是我个人认为这更加简洁。 - Binke
2
这可能会导致意外的错误,因为它对于小于10的情况输出一个字符串,而对于大于等于10的情况输出一个数字。 - David Fregoli
@DavidFregoli,所有这些日期转字符串函数都返回一个字符串,所以如果你输入一个字符串,pad也只会输出字符串。 - tim-phillips

81

给未来的你(ECMAScript 2017及以上版本)

解决方案

"use strict"

const today = new Date()

const year = today.getFullYear()

const month = `${today.getMonth() + 1}`.padStart(2, "0")

const day = `${today.getDate()}`.padStart(2, "0")

const stringDate = [day, month, year].join("/") // 13/12/2017

说明

String.prototype.padStart(targetLength[, padString])方法将尽可能多的padString添加到String.prototype目标中,以使目标的新长度为targetLength

示例

"use strict"

let month = "9"

month = month.padStart(2, "0") // "09"

let byte = "00000100"

byte = byte.padStart(8, "0") // "00000100"

4
这部分是 ES2017 或 ES8 的一部分。因此,说“ES6+”是不正确的,因为它不属于 ES6 和 ES7。 - Noel Llevares
1
这在技术上应该是 .padStart(2, '0'),因为第二个参数是一个字符串,尽管除非你正在使用 TypeScript,否则这可能并不重要。 - bmaupin
这个解决方案非常优雅。 - Sixteen

57
您可以定义一个类似于 PHP 中的 "str_pad" 函数:
function str_pad(n) {
    return String("00" + n).slice(-2);
}

12
用“0”代替“00”就足够了。 - David Fregoli

18

我找到了最短的方法来做这件事:

 MyDateString.replace(/(^|\D)(\d)(?!\d)/g, '$10$2');

将在所有孤独的、只有一位数字的数字前添加前导零


我喜欢这个解决方案,你能否稍微解释一下那里发生了什么? - Gobliins
你能解释一下这是如何工作的吗?看起来是一个优雅的解决方案。 - SeaWarrior404
1
正则表达式查找最多三个组: $1 - 任何非数字符号(或行的开头) $2 - 任何数字 $3 - 任何非数字(可能不存在)然后,我们用捕获(匹配)的内容替换为 $1 +“0”+ $2,这在替换字符串中变成$10$2。 - Povesma Dmytro
它会查找单个数字(在任何其他符号之间),并在该单个数字之前添加零。 您可以尝试以下代码: S = ['1/2/16', '2.10.20', '3 5 9', 'Today is 4.5.20', 'US style 3/9/21']; S.forEach(s => console.log(s.replace(/(^|\D)(\d)(?!\d)/g, '$10$2'))) - Povesma Dmytro
您的正则表达式中不存在 $3,而 (?!\d)负向前瞻语法,如果有多位数字,则不会添加前导零。 - Chupo_cro

12
Number.prototype.padZero= function(len){
 var s= String(this), c= '0';
 len= len || 2;
 while(s.length < len) s= c + s;
 return s;
}

//正在使用:

(function(){
 var myDate= new Date(), myDateString;
 myDate.setDate(myDate.getDate()+10);

 myDateString= [myDate.getDate().padZero(),
 (myDate.getMonth()+1).padZero(),
 myDate.getFullYear()].join('/');

 alert(myDateString);
})()

/*  value: (String)
09/09/2010
*/

10

现在你也可以使用String.prototype.padStart以快速简便的方式实现这个目标。

String(new Date().getMonth() + 1).padStart(2, '0')

可在 caniuse 中评估可用性。

var date = new Date()

var year = date.getFullYear()
var month = String(date.getMonth() + 1).padStart(2, '0')
var day = String(date.getDate()).padStart(2, '0')

console.log('%s/%s/%s', month, day, year)

检查

var date = new Date('7/4/2021')
    
var year = date.getFullYear()
var month = String(date.getMonth() + 1).padStart(2, '0')
var day = String(date.getDate()).padStart(2, '0')
    
/**
 * Expected output: 07/04/2021
 */
console.log('%s/%s/%s', month, day, year)

老版本浏览器的Polyfill

String.prototype.padStart || Object.defineProperty(String.prototype, 'padStart', {
    configurable : true,
    writable : true,
    value : function (targetLength, padString) {
        'use strict'
        /**
         * String.prototype.padStart polyfill
         * https://dev59.com/FnA65IYBdhLWcg3w1SbU
         */
        targetLength = targetLength | 0
        padString = arguments.length > 1 ? String(padString) : ' '

        if (this.length < targetLength && padString.length) {
            targetLength = targetLength - this.length

            while (padString.length < targetLength) {
                padString += padString
            }

            return padString.slice(0, targetLength) + this
        } else {
            return this
        }
    }
})

8
var MyDate = new Date();
var MyDateString = '';
MyDate.setDate(MyDate.getDate());
var tempoMonth = (MyDate.getMonth()+1);
var tempoDate = (MyDate.getDate());
if (tempoMonth < 10) tempoMonth = '0' + tempoMonth;
if (tempoDate < 10) tempoDate = '0' + tempoDate;
MyDateString = tempoDate + '/' + tempoMonth + '/' + MyDate.getFullYear();

8

解决这个问题的另一种方法是使用 JavaScript 中的 slice

var d = new Date();
var datestring = d.getFullYear() + "-" + ("0"+(d.getMonth()+1)).slice(-2) +"-"+("0" + d.getDate()).slice(-2);

datestring 返回的日期格式符合您的期望: 2019-09-01

另一种方法是使用 dateformat 库:https://github.com/felixge/node-dateformat


注意拼写“JavaScript”。 - Basil Bourque

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