Hello World
Spiga

深入JavaScript与.NET Framework中的日期时间(2):JavaScript中的Date类型(上)

2007-06-06 14:02 by 老赵, 5833 visits

概念

在JavaScript中处理时间使用的就是Date原生类型了,这也是在使用JavaScript进行开发时最常用的对象之一。JavaScript中Date类型的功能,与一些成熟编程环境的日期时间对象相比的确功能有些欠缺,但是已经足够我们在一般情况下的使用了。如果需要有什么特殊的要求,可以使用JavaScript的动态性扩展Date类型的功能,正如Microsoft AJAX Library那样。

既然我们要“深入”JavaScript的Date类型,那么我们先来搞清楚它到底是什么。首先,这是一个数据类型,它的实例是一个数据对象——这个从理解上应该没有问题。其次,它的每个实例其实维护的都仅仅是一个数字,这点可能需要详细解释一下。这个数字的含义是相对于UTC时间1970年1月1日0时整的时间偏移量,单位是毫秒,在JavaScript中每个Date类型实例都是使用这种方式来记录一个时间。理论上说,这是一个“ECMAScript number”类型的数字,表示的范围是从-9,007,199,254,740,991到9,007,199,254,740,991的整数,这使得每个Date类型的实例能表示时间范围是相对于UTC时间1970年1月1日0时整,正负各285,616年。不过实际上Date类型能够表示的时间是相对正负各100,000,000天,略小于285,616年,不过也足够我们使用了。

这段理解根据ECMAScript Language Specification所得,至于每个脚本引擎的实现方式并不在我们关心的范围之内。请注意上面的说法是:每个实例维护的“仅仅是”一个数字,这代表在JavaScript中,两个Date对象的这个数字相同,即代表这两个对象表示的时间相同,这一点并不像.NET Framework中每个DateTime对象还维护着自身的类型信息(表示UTC时间,表示本地时间亦或都不表示,这点在今后的文章中我会详细描述)一样。说的再简单一些,JavaScript中的Date类型表示(记录?维护?)的永远是UTC时间。 

根据Spec的说法,这个“数字”被称为time value。

 

Date函数

这里说的Date函数并非是指构造Date类型对象所用的构造函数,而仅仅是把Date作为一个普通函数所使用。它只有一种调用方式:

  • Date ( [ year [, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] ] ] )

例如:

var d = Date(2000, 1, 1);

有意思的是,Spec对于这个调用的描述非常有趣:“All of the arguments are optional; any arguments supplied are accepted but are completely ignored.”,也就是说,无论您传入任何的参数都会被忽略。这个调用返回的时一个字符串,用于表示当前时间。按照Spec的定义,它与下面的代码所得结果相同:

new Date().toString()

可惜在IE中,Date()返回的结果是“Mon Jun 04 11:12:22 2007”,而new Date().toString()返回的结果是“Mon Jun 4 11:12:22 UTC+0800 2007”。在FireFox中,两者都返回“Mon Jun 04 2007 11:12:22 GMT+0800”。在这点上,FireFox更符合标准。

不过,在实际开发时中几乎不会使用这种方法。

 

Date对象的构造

构造一个Date对象有以下三种方式: 

  1. new Date()
  2. new Date(value)
  3. new Date (year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )

例如:

var d1 = new Date() // 构造一个表示当前时间的对象
var d2 = new Date(0); // 构造一个表示UTC时间1970年1月1日0时整的对象
var d3 = new Date(2007, 5, 6); // 构造一个表示本地时间2007年6月6日0时整的对象

经过上面的代码之后,d1表示的是构造那一刻的时间。请注意它并不区分本地时间还是UTC时间,时间只有一个,UTC时间也好本地时间也罢,这只是同一个时间的不同表现形式而已。d2对象在构造时只接受了一个参数,因此这个参数将会被作为相对于UTC时间1970年1月1日0时整的偏移毫秒数,也就是time value。如果使用了多个参数来构造Date对象,则参数会被依次认作为年、月、日,直到最后个参数表示毫秒。除了年和月之外,所有的参数都是可选的,不提供的参数使用0作为其默认值。关于这个构造方式有两点是需要注意的:

  1. “月份”从0开始计算:在JavaScript中,Date类型对象的Month值是从0开始计算的,也就是说使用0到11来表示1月到12月。因此上例的代码中构造的时6月4日而不是5月4日。这一点常常被人忽视,甚至会被认作是JavaScript的bug,其实这一点在Spec上写的清清楚楚。
  2. 参数表示的是本地时间信息:上例的代码所构造出的时间对象表示2007年6月6日0时整,请注意这是站在“本地时间”的角度来考虑的。例如,我在时区设置为UTC +8的系统上调用new Date(2007, 5, 6)构造出的其实是UTC时间2007年6月5日16点整。

我们通过new关键字并指定年、月、日等信息构造出的Date对象是基于本地时间的,那么我们该如何构造出一个有特定年、月、日等UTC时间信息的对象呢?我们只能间接地这么做,因为JavaScript只提供了一个Date.UTC方法,它的方法签名如下:

  • Date.UTC (year, month [, date [, hours [, minutes [, seconds [, ms ] ] ] ] ] )

这个方法的作用是根据指定的年、月、日等UTC时间信息,返回一个time value值,通过这个值,我们就可以使用上面的第二种方法来构造一个Date对象了,如下:

var d = new Date(Date.UTC(2007, 5, 6)); // 构造一个表示UTC时间2007年6月6日0时整的对象

一般来说,我们最常用的构造Date对象的方法就是上述这些。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

19 条回复

  1. Frank[callfrank@gmail.com][未注册用户…
    *.*.*.*
    链接

    Frank[callfrank@gmail.com][未注册用户] 2007-06-06 14:26:00

    沙发

  2. freetofly[未注册用户]
    *.*.*.*
    链接

    freetofly[未注册用户] 2007-06-06 14:55:00

    板凳

  3. Anthan
    *.*.*.*
    链接

    Anthan 2007-06-06 15:00:00

    受教了,以前只关日期时间在客户端的呈现格式而忽略了这么重要的内容。
    准确性是基础,格式是进阶...

  4. luoluo[未注册用户]
    *.*.*.*
    链接

    luoluo[未注册用户] 2007-06-06 15:11:00

    呵呵...还没达到深究Date这么仔细的地步!不过很是受教!

  5. 老赵
    admin
    链接

    老赵 2007-06-06 15:33:00

    @Anthan
    下一次会讲到格式方面的问题,包括默认格式,系统格式等等。:)

  6. Anthan
    *.*.*.*
    链接

    Anthan 2007-06-06 16:42:00

    @Jeffrey Zhao
    恩,我过多的关注了格式方面的问题,不过这也是用户需求所致。呵呵
    我们的系统虽然是全球的,不过是每个地方各上一套

  7. 老赵
    admin
    链接

    老赵 2007-06-06 17:34:00

    @Anthan
    每个地方各上一套?这是什么意思呢?

  8. Anthan
    *.*.*.*
    链接

    Anthan 2007-06-06 20:21:00

    @Jeffrey Zhao
    全球有N个分公司,每个分公司就上属于自己的一套,日期,时间,货币,语言等等就由当地分公司的ITS根据自己的需要去配置而不是follow服务器的配置

  9. 老赵
    admin
    链接

    老赵 2007-06-06 20:49:00

    @Anthan
    这个做法是比较简单,但是工作量比较大哎。

  10. Anthan
    *.*.*.*
    链接

    Anthan 2007-06-06 21:24:00

    @Jeffrey Zhao
    是的,要维护很多套系统,所以现在也在做一些ASP模式的项目。
    还需要多多从你这学习才能做好这种

  11. 老赵
    admin
    链接

    老赵 2007-06-06 22:01:00

    @Anthan
    其实做项目的Localization和Globalization是很复杂和浩大的工程,实际情况下各种复杂的问题也会出现很多,一起学习体会。:)

  12. MK2
    *.*.*.*
    链接

    MK2 2007-06-06 23:23:00

    呵呵,6月6日....

    支持中文,呵呵。

  13. 老赵
    admin
    链接

    老赵 2007-06-07 01:27:00

    @MK2
    什么?

  14. YAO.NET℡
    *.*.*.*
    链接

    YAO.NET℡ 2007-06-07 09:43:00

    晕.看成Java 了.

  15. Join miao
    *.*.*.*
    链接

    Join miao 2007-06-07 22:44:00

    不错。学习了!

  16. 乐趣电子书[未注册用户]
    *.*.*.*
    链接

    乐趣电子书[未注册用户] 2007-06-07 23:06:00

    每个地方各上一套?这是什么意思呢?

  17. chenqi1000y[未注册用户]
    *.*.*.*
    链接

    chenqi1000y[未注册用户] 2007-09-09 00:53:00

    原来javaScript的Data是以毫秒进行判断的!!
    这是我最能知道的一句话喽!!!并不懂全部,但我最少能知道一些我所知道的:)
    你博客的好东西真多》》》

  18. lx[未注册用户]
    *.*.*.*
    链接

    lx[未注册用户] 2008-01-04 09:56:00

    谢谢!

  19. 静儿[未注册用户]
    *.*.*.*
    链接

    静儿[未注册用户] 2008-04-01 15:49:00

    我想用javascript实现日期格式的转换,如:把2008年4月1日转成2008/4/1?

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我