日期处理

ZDNet软件频道 时间:2000-05-23 作者:Nathan Torkington |  我要评论(8)
本文关键词:
人类文明的历史进程是通过精确的日期和时间来刻划的, 让我们来看看Perl 程序员是如何处理日期的

日常生活所用的日期和时间的表示

你已经级掌握了时,分,年等值的含义,也了解了纪元秒的含义。而日常生活中的日期和时间是用字符串来表示的,你怎样才能把日常所用的日期和时间串格式转换成纪元秒呢?

方法之一是写出语法分析小程序,该方法灵活而快速:

use Time::Local;

@months{qw(Jan Feb Mar Apr May Jun

     Jul Aug Sep Oct Nov Dec)} = (0..11);

$_ = "19 Dec 1997 15:30:02";

/(dd)s+(w+)s+(d+)s+(d+):(d+):(d+)/

     or die "Not a date";

$mday = ;

$mon  = exists($months{}) ? $months{} : die

     "Bad month";

$year = — 1900;

($h, $m, $s) = (, , );

$epoch_seconds = timelocal($s,$m,$h,$mday,$mon,$year);

一个更通用些的方法,是从CPAN(Perl综合网)中安装Date::Manip 模块。

use Date::Manip;

$epoch_seconds = UnixDate("19 Dec 1997     15:30:02","s");

注意,由于 Date::Manip是个大模块,使用该模块时,将会增加你的程序的启动时间。其中一个原因是 Date::Manip将对多种不同的格式进行识别,如:

"today"

"now"

"first sunday in april 2000"

"3:15, today"

"3:15pm, first sunday in april 2000"

"2000/01/18 09:15"Date Manipulation

2036, 2037, 2038, ..., 1901?!

大多数C程序把纪元秒存为有符号整数,可表示正的和负的日期,但计算机存储器所表示的整数大小是有限的,用有限的位数来表示秒。这就是说,我们在计算纪元秒时,所表示的日期是有限制的。

确切的限度取决于你的机器所能表示的整数的位数。 Perl最多以32位的长度存储整数。粗略地讲,有一位用来表示正负号,其余31位来表示数。如果8位,你可以存储的最大数是255,即2的8次方减1。故Perl中所存储的32位符号数中的最大数为:

print 2**31–1, " ";

2147483647

这个数字对应了哪个日期呢?

print scalar(gmtime 2**31-1), " ";

Tue Jan 19 03:14:07 2038

在那个时刻的1秒之后会发生什么呢?

print scalar(gmtime 2**31), " ";

Fri Dec 13 20:45:52 1901

啊!发生了什么?对于32位有符号整数来说, 2**31太大了。它“翻卷过去了”,其符号位被置为负号,因而成为了所能表示的最大负数。这对应于1970年开始时刻之前的秒的最大值。

其结果说明了什么呢?你不能存储gmtime(2**31)之前或gmtime(2**31-1)之后的以纪元秒表示的日期。

你可千万不要想不开,这可不是什么大问题。如果你要用到32位有符号整数表示的纪元秒以外的时间,你只需要改变你的表示方式,你可从CPAN中找到不少日期模块,其中的Date::Calc 和Date::Manip 很可能是功能最强的两个模块。

这两个模块使用自己的日期表示方式,以避免Y1901-Y2038 的限制。 Date::Manip 使用罗马历法,从公元 0000 到公元9999。 Date::Calc 也使用罗马历法,可表示的年份从1 到 32767。

上一页 下一页
常见的日期和时间操作 总结

百度大联盟认证黄金会员Copyright© 1997- CNET Networks 版权所有。 ZDNet 是CNET Networks公司注册服务商标。
中华人民共和国电信与信息服务业务经营许可证编号:京ICP证010391号 京ICP备09041801号-159
京公网安备:1101082134