JavaScript中的对象:Date日期对象

JavaScript中的日期对象——Date,是JavaScript常用内置对象的成员之一,它为我们提供了对客户端系统时间的访问,也提供了大量的属性和方法方便我们对特定的日期或者时间进行处理。例如显示在网页中的电子时钟、又或者是某项活动的倒计时,再者复杂到一个日期显示插件等都需要通过Date对象来进行辅助处理。

在JavaScript中,每个Date对象的实例都是通过一个叫作“时间戳”的概念来保存日期时间的。时间戳是指自UTC(Coordinated Universal Time,国际协调时间)1970年1月1日午夜(0时)开始到现在所经过的毫秒数,而这个时间点我们为了方便描述而将其称为JavaScript中的时间基点。在使用这种方式存储时间的条件下,一个Date对象保存的日期可以精确到1970年1月1日之前或之后的285,616年。

日期对象的创建

创建日期对象最快捷的方式,就是通过new操作符来构建Date构造函数的一个对象实例,代码如下:

var now = new Date();

上面语句创建的日期对象表示的是用户当前系统的时间,你可以通过alert(now)或者document.write(now)在页面中直接输出该对象的字符串信息来进行查看。在我本人电脑测试了IE8、IE11、Firefox、Chrome四个浏览器,他们的输出信息分别如下(demo):

尽管测试的结果在不同浏览器中存在微小的差别,但他们表达的时间是一样的——即2014年08月10日 星期日 15时45分19秒,其中+0800的含义是指当前系统的时间与国际UTC时间的时差为08时00分。

UTC和GMT的术语解释

在正式步入Date对象的详细介绍之前,在这里我们不得不先解释下UTCGMT这两个专业的时间名词。

GMT的全称是格林尼治时间(Greenwich Mean Time, GMT),是指位于伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义为在那里通过的经线。理论上来说,格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时的时间。

格林尼治标准时间是19世纪中叶大英帝国的基准时间,同时也是事实上的世界基准时间,当时主要是为1840年之后的铁路系统服务。它以格林尼治天文台的经线为0度经线,将世界分为了24个时区,而我们中国大陆、中国香港、中国澳门、中国台湾、蒙古国、新加坡、马来西亚、菲律宾、西澳大利亚州的时间则被划分在时八区,所以在上面浏览器的信息输出中,我们可以看到GMT+0800的字眼。

由于地球在它的椭圆轨道里的运动速度不均匀,这个时刻可能和实际的太阳时相差16分钟。再加上地球每天的自转是有些不规则的,而且正在缓慢减速。所以,格林尼治时间已经不再被作为标准时间使用,其先后被历书时(1960年)和原子时(1967年)所取代。

原子时与以往的计时系统不同,它非常精确并且不以某地的平均太阳时为基准。原子时由原子钟提供,它的准确度为每日数纳秒,而世界时(格林尼治时间)的准确度则为每日数毫秒。再加上地球自转速度不均匀,原子时与世界时之间的时差便日积月累。对于这种情况,一种称为协调世界时(Coordinated Universal Time)的折衷时标于1972年面世。为了确保协调世界时与世界时相差不会超过0.9秒,在有需要的情况下会在协调世界时内加上正或负的闰秒来补偿,位于巴黎的国际地球自转事务中央局(IERS) 负责决定何时加入闰秒。

协调世界时(Coordinated Universal Time),又称为世界统一时间,世界标准时间,国际协调时间,为了方便通常被记成Universal Time Coordinated,即UTC。同样为了方便,在不需要精确到秒的情况下,通常也将GMT和UTC视作等同。

到此,我们就不过多地去追逐历史,也无需探讨原子时的工作原理,至少我们知道UTC时间与GMT时间在一定程度上保持了一致性,即使两者之间存在着微妙的时间差。那么接下来,我们将继续深入了解关于Date对象的创建。

时间戳的计算

在调用Date构造函数时如果不传递参数,那么创建的Date对象返回的是当前系统的日期时间。如果需要根据特定的日期和时间来创建对象,则必须向Date构造函数传递一个时间戳的参数(即从1970年1月1日0时开始所经过的毫秒数)。为了简化这一计算过程,JavaScript提供了Date.parse()Date.UTC()这两个内置方法来做计算处理,同时还提供了Date.now()这一特殊方法。

  1. Date.parse(dateStr)

    该方法将根据传递过来的日期字符串,将其解析为时间戳并返回。(返回类型:Number)

    如果没有参数传递,或者传递过来的参数不是一个有效的日期时间,那么最终结果将返回NaN。

    参数dateStr:(类型:String)日期字符串;

    该方法支持的日期字符串的常见格式我们按美国习惯和中国习惯来进行分类描述。

    美国习惯

    • 月/日/年 时:分:秒Date.parse("8/10/2014 20:00:00")(24小时)
    • 月/日/年 时:分:秒 上下午Date.parse("8/10/2014 8:00:00 pm")(12小时)
    • 月 日,年 时:分:秒Date.parse("August 10,2014 20:00:00")(24小时制)
    • 月 日,年 时:分:秒 上下午Date.parse("August 10,2014 8:00:00 PM")(12小时制)

    中国习惯

    • 年/月/日 时:分:秒Date.parse("2014/8/10 8:00:00")(24小时制)

    说明事项

    • 在上面所述的日期格式中,我们可以只保留日期部分而舍弃时间部分,此时的时间部分将默认为“0时0分0秒”。
    • Date.parse()函数中,所有的时间信息都是基于本地时区的结果。

    除了上述各大浏览器所支持的标准格式外,不得不说下我们还习惯使用的其它格式:

    • 年-月-日 时:分:秒Date.parse("2014-8-10 8:00:00")(24小时制)
    • 年.月.日 时:分:秒Date.parse("2014.8.10 8:00:00")(24小时制)

    可惜上面两种日期格式在JavaScript中并没有得到支持(不过在Chrome以及Webkit版的Opera浏览器中有效),这也使得我们无缘去使用它们。

    关于无效的日期时间

    Date.parse()函数中,除了上面美国习惯和中国习惯所描述的一些最基本的字符串格式外,其实还有其他一些格式是被支持的,但是这些格式并不是我们生活中所使用的,所以我们姑且将他们忽略,但至少需要知道有这么一件事情存在。

    在前面有谈到,如果该函数的参数不是一个有效的日期字符串,那么将会返回NaN,即解析失败所得的结果。而在网站应用中,通常会有要求输入日期的文本框,那么我们该如何去判断这个字符串是不是一个有效的日期呢?大家第一时间可能想到的是——直接通过Date.parse()返回的结果来进行判断。在一定程度上,这种做法是有效的,但实际应用中我们不能这样使用。

    原因很简单,那就是各大浏览器对EcmaScript的实现是不尽相同的。其中最为突出的问题,就是针对日期时间的值超出限定范围时的处理机制,例如:"2014/12/31"是一个绝对正确的时期字符串,但是"2014/12/32"还是一个有效的日期字符串吗?又或者是"2014/12/31 08:61:00"的这类情况呢?对于这一情况,在各大浏览器中存在如下差异:

    • Chrome以及Webkit版的Opera将超出限定范围的日期时间字符串作为无效格式进行处理;
    • Firefox以及Presto版的Opera将超出限定范围的日期时间字符串作为有效格式进行处理,超出的部分将通过等值换算累加到前面的日期时间部分。例如,“2014/12/32 08:61:00”,将会等值换算为“2015/01/01 09:01:00”。
    • IE以及Safari允许日期部分超出限定值,处理方式同上。而如果时间部分超出了限定值,那么最终结果也将返回NaN。

    所以说,在日期时间的有效性判断方面,并不能依赖于Date.parse()的返回结果,而是需要根据我们自己的业务需求进行合理的自定义处理。

    关于上面所提到的所有日期格式,你可以查看案例演示来帮助自己更好地理解。

  2. Date.UTC(year, month, day, hours, minutes, seconds, milliseconds)

    该方法将根据传递过来的各日期时间的组成部分,将它们解析为时间戳并返回。(返回类型:Number)

    如果没有传递参数、或者要求传递的参数没有提供,那么最终结果将返回NaN。

    参数year:(类型:Number)年份,要求不能缺省;

    参数month:(类型:Number)月份,要求不能缺省,数值范围为0~11(0表示1月份,11表示12月份);

    参数day:(类型:Number,可选)当月的第多少天,默认为1;

    参数hours:(类型:Number,可选)小时数,默认为0;

    参数minutes:(类型:Number,可选)分钟数,默认为0;

    参数seconds:(类型:Number,可选)秒数,默认为0;

    参数milliseconds:(类型:Number,可选)毫秒数,默认为0;

    需要注意的是,与Date.parse()不同,Date.UTC()函数是基于UTC来计算的,当你传递小时数为0的时候,在我国(中国北京,时八区)将表示为8点。另外当日期时间部分超出限定值时(为了方便描述,我将其称呼为"超值"),在所有浏览器中都将会向前面的日期时间部分进行换算累加(例如:当小时数为61时,会在天数上面+1,而小时数变更为1)。代码示例如下:

    //返回UTC时间2014年08月10日8点30分45秒的时间戳
    var res1 = Date.UTC(2014, 7, 10, 8, 30, 45);
    
    //下面提供的参数将利用超值特点返回跟上面代码一样的结果
    var res2 = Date.UTC(2014, 6, 41, 8, 29, 105);
    
    //返回北京时间2014年08月10日8点30分45秒的时间戳
    var res3 = Date.UTC(2014, 7, 10, 0, 30, 45);
    

    关于各参数的缺省情况以及超值特点的返回结果,你可以查看案例演示来进行核对。

  3. Date.now()

    返回当前系统日期时间的时间戳。(返回类型:Number)

    该方法在IE6~8的安装版本中不被支持,但是在高版本的IE浏览器中选择这些版本的文档模式是可以被支持的,建议大家对该方法做兼容处理来进行使用。兼容代码如下:

    //兼容IE6~8:返回当前日期时间的时间戳
    Date.now === undefined && (Date.now = function(){
        return new Date().getTime();
    });
    

    你可以查看案例演示来加深对它的印象。

回归Date对象的创建

在上面我们有谈到,当我们在Date构造函数的调用中如果没有传递任何参数,那么此时创建的Date对象表示的是当前系统的日期时间。如果要根据特定的日期来创建Date对象,那么必须向Date构造函数传递一个基于时间基点的时间戳。代码示例如下:

//创建表示“1970年1月1日0时0分0秒”的日期对象
var dt1 = new Date(0);

//创建表示“1970年1月1日1时0分0秒”的日期对象
var dt2 = new Date(3600000);

//创建表示“2014年08月10日8时0分0秒”的日期对象
var dt3 = new Date(1407657600000);

需要强调的是,向Date构造函数传递时间戳所创建的时间是基于UTC进行计算的。例如上面所示的new Date(0),在我们国家(中国北京)实则表示的是1970年1月1日8时0分0秒。

由于时间戳不容易理解,再加上各地区时区的差异性,让我们不得不对使用时间戳的创建方式说“no”,而寻求其他更为便捷、更易理解的方式来创建日期对象。为此,JavaScript中提供了其他两种方式来创建日期对象。代码示例如下:

//创建表示“1970年1月1日0时0分0秒”的日期对象
var dt1 = new Date("1970/1/1 0:00:00");

//创建表示“2014年08月10日8时0分0秒”的日期对象
var dt2 = new Date(2014,7,10,8,0,0);

相信大家对上面的这两种参数形式有点眼熟,没错,它们就是Date.parse()Date.UTC()提供的参数类型。其实是这样的,当在Date构造函数中提供这两种参数格式的情况下,Date构造函数内部会对参数格式进行判断,如果是日期字符串则调用Date.parse()将其计算为时间戳再进行日期对象的构建,而如果是日期时间的各组成部分则调用Date.UTC()将其计算为时间戳再进行日期对象的构建。是不是觉得很有趣呢!

由于构造函数内部使用的是Date.parse()Date.UTC()进行的处理,所以对于上面两种格式的参数类型和注意事项都是一致的,在这里就不做重复说明。唯一需要强调的是,通过new Date()传递这两种格式的参数来构建日期对象,其内部已经做了本地时区的兼容处理,所以我们无须担心不同地区的时差问题。例如,上述的new Date(2014,7,10,8,0,0),无论在哪个地区,都表示的是当地时间的“2014年08月10日8时0分0秒”,而非UTC时间。

为了提高new Date()的兼容处理,当我们向该函数传递一个日期对象时,该函数将返回该对象的一个副本。

下面,就让我们一起来整理下关于Date对象创建的几种方式:

  1. 无参数new Date(),创建表示当前系统日期时间的Date对象。
  2. 时间戳new Date(3600000),创建自时间基点之后所经过的毫秒数的Date对象(UTC时间)。
  3. 日期字符串new Date("2014/8/10"),创建与日期字符串等值的Date对象。
  4. 日期时间组成部分new Date(2014,7,10),根据日期时间的各组成部分进行计算合并来创建与其等值的Date对象。
  5. 日期对象new Date( new Date("2014/8/10") ),返回日期对象的一个副本。

为了帮助大家更好地理解new Date()执行语句的返回结果,我们整理了一份简易的测试页面——将使用不同参数类型构建的Date对象通过document.write进行输出以便验证,你可以点击案例演示来进行查看。

关于new Date()的补充

JavaScript是通过时间戳的概念来保存日期时间的,这也给我们判断两个日期时间的大小关系提供了非常好的便捷性——当我们对两个Date对象执行算术运算或比较运算时,JavaScript会将他们转换为数值类型(即该日期对象的时间戳)再进行处理。所以,在JavaScript中你可以像下面这样来使用Date对象:

var dt1 = new Date("2014/8/10 8:00:00");
var dt2 = new Date("2014/9/10 8:00:00");

//获取Date对象的时间戳
alert("dt1的时间戳是:" + +dt1);
alert("dt2的时间戳是:" + +dt2);

//计算两个Date对象之间相差的时间戳
alert("dt1和dt2之间相差的毫秒数为:" + (dt2 - dt1));

//判断两个Date对象的大小关系
if(dt2 > dt1){
    alert("dt2的日期时间位于dt1之后!");
}else{
    alert("dt2的日期时间位于dt1之前!");
}

点击案例演示来查看上述代码的执行结果。

Date对象的字符串输出

在文本开篇的讲解中,我们通过document.write(new Date())语句将当前系统的日期时间以某种字符串格式输出来帮助理解new Date()的作用。在这里需要把这一操作进行下解释说明——Date对象保存的并不是日期时间的字符串信息,而是将Date对象参与字符串类型的操作时,JavaScript会隐式调用Date对象的.toString()方法来返回Date对象的日期时间字符串。

除了.toString()方法之外,JavaScript中还为Date对象提供了多个用于字符串输出的方法,现汇总如下(由于不同时区、不同系统设置的输出结果会有所不同,下面的演示结果均以本人电脑为依据——中国北京,Windows 7操作系统,Chrome浏览器):

  1. .toString()

    将当前Date对象的日期时间输出为标准的GMT格式(本地时区)。(返回类型:String)

    例如:2014年8月10日上午8点整,将输出为:Sun Aug 10 2014 08:00:00 GMT+0800 (中国标准时间)

  2. .toDateString()

    将当前Date对象的日期部分输出为标准的GMT格式(本地时区)。(返回类型:String)

    例如:2014年8月10日上午8点整,将输出为:Sun Aug 10 2014

  3. .toTimeString()

    将当前Date对象的时间部分输出为标准的GMT格式(本地时区)。(返回类型:String)

    例如:2014年8月10日上午8点整,将输出为:08:00:00 GMT+0800 (中国标准时间)

  4. .toLocaleString()

    将当前Date对象的日期时间输出为当前系统的本地格式(长日期、长时间)。(返回类型:String)

    由于该方法采用本机系统的日期时间格式来进行输出,所以会因用户系统设置的不同而输出不同的结果。

    例如:2014年8月10日上午8点整,在本人的电脑上输出为:2014年8月10日 上午8:00:00

  5. .toLocaleDateString()

    将当前Date对象的日期部分输出为当前系统的本地格式(长日期)。(返回类型:String)

    例如:2014年8月10日上午8点整,在本人的电脑上输出为:2014年8月10日

  6. .toLocaleTimeString()

    将当前Date对象的时间部分输出为当前系统的本地格式(长时间)。(返回类型:String)

    例如:2014年8月10日上午8点整,在本人的电脑上输出为:上午8:00:00

  7. .toUTCString()

    将当前Date对象的日期时间输出为UTC时间的GMT格式。(返回类型:String)

    例如:2014年8月10日上午8点整,将输出为:Sun, 10 Aug 2014 00:00:00 GMT

  8. .toGMTString()

    该方法同.toUTCString()一样,将当前Date对象的日期时间输出为UTC时间的GMT格式。(返回类型:String)

    该方法的存在是为了向后兼容,如果需要输出UTC时间,请使用.toUTCString()代替。

    例如:2014年8月10日上午8点整,将输出为:Sun, 10 Aug 2014 00:00:00 GMT

当Date对象是一个无效的日期时间时,在IE6~8中,上述方法输出的内容为“NaN”,而在其他浏览器中输出的内容则为“Invalid Date”。

在上面所述的将日期时间输出为字符串信息的几种方法中,除了输出为当前系统的本地格式的那三个方法外,其他方法我们可能永远也无需使用。即使输出为本机格式的那三个方法,也会由于输出格式的限定而不会用于具体的网页需求中去。虽然如此,我们还是需要去了解它们的存在,或许它们在哪一天会给我们提供用于解决实际问题的思路。现在,你可以点击案例演示来查看上述方法的执行结果。

Date对象的信息获取

相信大家在生活中会经常看到电子时钟的影子,就是在电子显示屏上打印当天的日期和时间信息,并且时间部分按秒在不停地进行累计。你可以点击这里来查看Web版电子时钟的一个简单案例。在实现这一电子时钟的时候,我有考虑过使用.toLocaleString()来进行字符串的输出,但是它的输出结果并不能满足我的格式要求。那么这个时候,就需要通过特定的方法来获得日期时间的各组成部分,然后再通过相关处理将他们组合成一个符合我们需求的日期时间字符串。

日期时间各组成部分

要获得某个Date对象的日期时间的各组成部分是非常方便的,JavaScript为Date对象提供了一系列的方法来帮助达到目的,现罗列如下:

  1. .getFullYear():获取完整的年份(4位)。
  2. .getMonth():获取月份(0~11,0表示1月份,11表示12月份)。
  3. .getDate():获取日期(一个月的多少号)。
  4. .getDay():获取星期(0~6,0表示星期日,6表示星期六,星期日为一周的第一天)。
  5. .getHours():获取时钟。
  6. .getMinutes():获取分钟。
  7. .getSeconds():获取秒钟。
  8. .getMilliseconds():获取毫秒值。

在上述列表中,所有方法的返回结果均为Number类型。如果Date对象不是一个有效的日期时间,那么这些方法的返回结果都将是NaN

上述的这些方法返回的都是用户系统的本地日期时间,例如new Date("2014/8/10 08:00:00").getHours()的返回结果就是8。另外,JavaScript也提供了另外一组方法,该组方法用来获取Date对象中各日期时间组成部分所对应的UTC时间。该组方法的命名是在上述方法名称的get字符后面加上"UTC"来构成,例如.getUTCFullYear().getUTCHours().getUTCMinutes()等。该组方法的返回值与前面所述的各方法主要存在一个时差的问题,例如在中国北京,new Date("2014/8/10 08:00:00").getUTCHours()的返回结果是0,而不是8。

为了进一步理解Date对象中各日期时间组成部分的获取情况,大家可以点击案例演示来进行快速核对。

不得不谈的Y2K问题

在前面的案例演示中,相信大家注意到了.getYear()这个方法,它的作用是用于获取年份的后两位数字,但是对于该函数的使用将会导致Y2K问题。

Y2K问题又称为2000年问题,大陆和香港常称为千年虫问题,这是由于计算机程序设计的一些问题,使得计算机在处理2000年1月1日以后的日期和时间时,可能会出现不正确的操作,从而可能导致一些敏感的工业部门(如电力、能源)和银行,政府等部门在2000年1月1日零点工作停顿甚至发生灾难性的结果。

Y2K问题源自于在计算机程序中使用两个数字来表示年份,如1998年被表示为“98”、1999年被表示为“99”,而2000年则被表示为“00”,这样将会导致某些程序在计算时得到不正确的结果,如把“00”误解为1900年。在嵌入式系统中可能存在同样的问题,这有可能导致设备停止运转或者发生更加灾难性的后果。

而在JavaScript中,.getYear()方法利用“把4位年份减去1900”的方式来取得两位年份的做法,而不是取年份的最后两位,因而会出现“不正常”的结果,例如将2014年显示为“114”。

那么为什么会出现来2000年问题呢?

这个问题可以追溯到1960年代,当时计算机内存和外部存储介质的成本很高,大多数数据处理需要借助于用穿孔卡片,它用80行文本表示所储存的数据。为了节省硬件成本,葛丽丝·霍普在Harvard Mark I上,以6位数字来存储时间,即年、月、日各两位。这个习惯被COBOL继承下来,传播到整个电脑程序界。

那个时候的编程语言,如COBOL和RPG,使用ASCII码和EBCDIC编码表示数据。如果用四位数字表示年份,就要多占用储存器空间,就会使成本增加,因此为了节省存储空间,计算机系统的编程人员采用两位数字表示年份,随着计算机技术的迅猛发展,虽然后来存储器的价格降低了,但在计算机系统中使用两位数字来表示年份的做法却由于思维上的惯性势力而被沿袭下来。对大多数程序员来讲,他们并不认为所编写的软件会持续使用很多年。

2000年问题是由Bob Bemer在1958年第一次提出的。在其后的二十年里,他用了很大的努力,希望政府、企业和国际组织(如IBM和ISO)来关注这个问题,但反响寥寥。直到2000年将要到来的时候,人们才感觉到两千年问题的紧迫性。于是社会和政府都投入了大量的人力和物力来避免发生大规模的计算机灾难。而从现在来看,这些努力也取得了相应的成果。

既然Y2K问题在1958年被提出,而JavaScript在1996年才被问世,那么为什么它还会提供.getYear()这个函数?

我们知道,JavaScript的作者在设计JavaScript的时候仅用了极短的时间,很多特性都借鉴了其他编程语言。而.getYear()这个函数的问题完全来源于Java,因为JavaScript的日期类直接采用了java.util.Date函数库。Brendan Eich显然很不满意这个结果,这导致后来不得不添加了一个返回四位数年份的.getFullYear()函数。

获取Date对象的时间戳

除了提供日期时间各组成部分的信息获取外,怎么能少了对时间戳的获取呢?在JavaScript中,你可以通过下列方式来获得一个Date对象的时间戳。

  1. .getTime()

    该方法将返回Date对象的毫秒快照。(返回类型:Number)

    如果Date对象是一个无效的日期时间,那么该方法的返回结果将为NaN。

    new Date().getTime()

  2. .valueOf()

    该方法将返回Date对象的原始值,其返回值同.getTime()的返回值相等。(返回类型:Number)

    该方法通常在一些隐式操作中由JavaScript在后台自动调用,并不显式地在出现在代码中。因此我们在获得一个Date对象的时间戳时,应使用.getTime(),而非该函数。

    new Date().valueOf()

  3. +new Date()

    该使用方式在“关于new Date()的补充”部分已经做了相关说明,当为Date对象执行算术运算或者比较运算时,JavaScript将隐式返回该对象的时间戳并参与运算。事实上,在JavaScript内部,这一隐式操作就是通过调用.valueOf()返回的结果。如同将Date对象参与字符串操作时,JavaScript会隐式调用.toString()返回字符串结果是一样的操作模式。

    由于这种方式JavaScript会隐式进行多项处理,所以并不建议如此使用,应尽量使用.getTime()来进行代替。

    +new Date()

最后需要强调的是,当我们在获取当前系统日期时间的时间戳时,不建议使用new Date().getTime()、以及+new Date()的方式来进行处理,而应该优先使用Date.now()来获得。毕竟该方法相对于其他两种方式而言更直接,其内部的处理操作也更少。

Date对象的有效性判断

在进行日期时间的操作处理的过程中,往往需要对该Date对象进行有效性判断。如果该Date对象不是一个有效的日期时间,那么就不应该继续执行后续的操作代码。那么,我们可以通过通过什么方式来做Date对象的有效性判断呢?

首先,当我们在获得一个Date对象的字符串信息时,如果该Date对象不是一个有效的日期时间,那么在标准浏览器中返回的是“Invalid Date”信息,但是在IE6~8的不标准模式下返回的确实“NaN”,所以我们不能通过aDateObejct.toString() === "Invalid Date"的方式去判断一个Date对象是否有效。

然后,我们看到,当获得Date对象的各日期时间的组成部分以及时间戳时,如果该Date对象不是一个有效的日期时间,那么最终将返回统一的NaN,所以我们就可以使用下述任意一种形式来做Date对象的有效性判断。如果返回true,则不是有效的Date对象:

  1. isNaN(aDateObject)
  2. isNaN(aDateObject.getTime())
  3. isNaN(aDateObject.getFullYear())
  4. isNaN(aDateObject.getMonth())
  5. isNaN(aDateObject.getHours())
  6. isNaN(aDateObject.getMinutes())
  7. ......

Date对象的信息修改

JavaScript提供了对Date对象中日期时间的各组成部分的信息获取,与其相对应的是,JavaScript也提供了一系列方法来对日期时间的各组成部分进行重新赋值,现罗列如下:

  1. .setFullYear(value):重置完整的年份(4位)。
  2. .setMonth(value):重置月份(0~11,0表示1月份,11表示12月份)。
  3. .setDate(value):重置日期(一个月的多少号)。
  4. .setDay(value):重置星期(0~6,0表示星期日,6表示星期六,星期日为一周的第一天)。
  5. .setHours(value):重置时钟。
  6. .setMinutes(value):重置分钟。
  7. .setSeconds(value):重置秒钟。
  8. .setMilliseconds(value):重置毫秒值。

针对上述方法,需要说明的事项有:

  1. 参数类型均为Number。
  2. 变更操作将改变原来Date对象的值。
  3. 执行完毕之后将返回变更后Date对象的时间戳,返回类型为Number。
  4. 与get系列方法一样,set系列方法也提供了针对UTC时间的重置处理,在此不作过多描述。
  5. 除了.setMilliseconds()之外,其他set方法允许提供多个参数部分。例如:.setSeconds(59, 800),表示将秒钟重置为59,同时将毫秒值重置为800;.setHours(10, 30, 56),表示将时钟重置为10、分钟重置为30、秒钟重置为56,毫秒值保持不变。
  6. 在设置时期时间的各组成部分时,允许值超出限定范围,此时将会把设定的值进行等值换算累加到前面的一个组成部分中去。

代码演示:

//dt对象表示的日期时间将变更为:2015/8/10 08:00:00
//value变量的值为变更后Date对象的时间戳:1439164800000
var dt = new Date("2014/8/10 08:00:00");
var value = dt.setFullYear(2015);

//dt2对象表示的日期时间将变更为:2015/10/09 08:00:00
//value2变量的值为变更后Date对象的时间戳:1444348800000
var dt2 = new Date("2014/8/10 08:00:00");
var value2 = dt2.setFullYear(2015, 9, 9);

//dt3对象表示的日期时间将变更为:2014/8/10 10:30:56
//value3变量的值为变更后Date对象的时间戳:1407637856000
var dt3 = new Date("2014/8/10 08:00:00");
var value3 = dt3.setHours(10, 30, 56);

//dt4对象表示的日期时间将变更为:2014/8/10 09:08:00
//value4变量的值为变更后Date对象的时间戳:1407632880000
var dt4 = new Date("2014/8/10 08:00:00");
var value4 = dt4.setMinutes(68);

课后总结/训练

关于JavaScript中Date对象的讲解到此就结束了,祝你学习愉快,同时也希望本篇教程能够为你解答对于Date对象的大部分疑惑。由于个人精力有限,教程中难免存在缺漏,如有相关建议请与我联系,在此先表示感谢!

在这里建议大家做一个自我检测,就是返回到本篇教程的目录部分,当你看到每一小节的标题时,是否能够联想到与此对应的相关内容,最好能够使用自己的语言来进行描述,当然有一个忠实的听众那是最好不过了。如果你能够很好的描述各部分的核心内容和注意事项,那么说明你对本篇内容已经掌握得非常可以了。如果你觉得描述起来有一定问题,或者无法回忆部分小结的主体内容。这也没关系。我在后面为你提供了多个关于Date对象的作业练习,相信有了这些编码训练,能够帮助你快速有效地加强对Date对象的掌握程度。

  1. 判断一个年份是否为闰年。demo
  2. 实现一个电子时钟,显示当前时间格式为——“现在是:2014年08月10日 星期日 15:41:32”。demo
  3. 判断一个日期字符串所表示的日期是否有效。demo
  4. 在文本框中输入日期字符串,要求所填的日期不能低于某个特定日期。demo
  5. 计算两个日期字符串相差多少天。demo
  6. 计算一个日期字符串所处的当月有多少天。demo
  7. 计算一个日期字符串为这一年中第几周的星期几。demo
  8. 假设我的出生日期是1990年6月24日,请计算出我的下一个生日是多少周岁,且还有多少天才是我的生日。demo
  9. 倒计时程序。【示例】距离圣诞节还有: 101天 23时 45分 52秒。demo
  10. 将日期时间按指定的字符串格式进行输出。例如:dateFormat(new Date(), "yyyy-MM-dd"),输出“2014-08-10”;而“yyyy年M月d日”则输出“2014年8月10日”。demo

    关于进行日期时间的字符串格式化时,要求格式化字符如下:

    分类 格式符 作用 示例
    年份 y 省略掉年份的世纪值,只显示具体年代值 如2008年显示为“08”
    yy 省略掉年份的世纪值,只显示具体年代值 如2008年显示为“08”
    yyy 显示年份的完整信息 如2008年显示为“2008”
    yyyy 显示年份的完整信息 如2008年显示为“2008”
    月份 M 显示一位月份值 如8月显示为“8”,12月显示为“12”
    MM 显示两位月份值 如8月显示为“08”
    MMM 显示月份的大写形式 如8月显示为“八月”
    MMMM 显示月份的大写形式 如8月显示为“八月”
    天数 d 显示一位天数值 如6日显示为“6”,23日显示为“23”
    dd 显示两位天数值 如6日显示为“06”
    星期 ddd 显示一位星期值 如星期一显示为“一”
    dddd 显示完整的星期值 如星期一显示为“星期一”
    时钟 h 显示一位12时制的时钟值 如18时显示为“6”
    hh 显示两位12时制的时钟值 如18时显示为“06”
    H 显示一位24时制的时钟值 如8时显示为“8”
    HH 显示两位24时制的时钟值 如18时显示为“18”
    分钟 m 显示一位分钟值 如5分显示为“5”
    mm 显示两位分钟值 如5分显示为“05”
    秒钟 s 显示一位秒钟值 如6秒显示为“6”
    ss 显示两位秒钟值 如6秒显示为“06”
    上下午 t 显示一位用来表示上下午的文字 如果时上午则显示“上”,下午则显示“下”
    tt 显示两位用来表示上下午的文字 如果是上午则显示“上午”,下午则显示“下午”