电信主站 网通分站
购买流程 付款方式 常见问题 在线提问 续租服务 购物车
用户名: 密 码: 忘记密码?
首 页
域名注册
虚拟主机
双线主机
服务器租用
VPS主机
企业邮局
代理专区
客服中心
虚拟主机行业资讯 虚拟主机评测对比 互联网最新动态 技术学院 站长资讯 在线教程 网站运营
搜索优化 服务器 网络编程 图形图象 站长之家 网页制作 操作系统
冲浪宝典 软件教学 视频通信 办公软件 邮件系统 网络安全 认证考试
您当前位置:西部数码->资讯中心-> 在线教程-> CGI
perl中的日期处理-CGI教程,CGI文档
作者:网友供稿 点击:22
  西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!虚拟主机可在线rar解压,自动数据恢复设置虚拟目录等.虚拟主机免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金!
文章页数:[1] 
日期处理
作者: nathan torkington
日期: 2000年05月23日
from:(www.zdnet.com.cn)

<编者按:人类文明的历史进程是通过精确的日期和时间来刻划的,在20世纪即将结束的时候,让我们来看看perl 程序员是如何处理日期的>

当新千年即将来临时,许多人才知道“millennium”这个单词中有两个“l”和两个“n”,还有些人才知道并不是所有的语言都拥有能够返回确定值的日期函数。在本栏目中,你将了解到perl是如何处理日期的,如何避免写出存在千年虫的程序,以及在y2.038k虫出现之前做出正确的决定。
日期是如何表示的
表示日期的方式多种多样:

"18 jan 1973"

"18/01/1973"

"01/18/1973"

"jan 18 1973"

"18-01-73"

"18-01-1973"

"01/73"

其中,一些格式适合用在email中,一些适用在http头中, 一些适合用在支票簿中,另外一些则仅适用于信用卡,其中一些格式含义不清(如“01-06-1973”是表示6月1日呢,还是表示1月6日呢?)  如果不规定日期的表示形式,是很难处理日期的。

如果你想了解“18 jan 1973“和“6 sep 1950”之间的区别,你需要把它们转换为数字表示。unix 内部使用纪元秒表示时间。日期和时间加起来表示之自格林威志时间1970年1月1日午夜时分(纪元)到当前时刻之间的秒数。“18 jan 1973” (假定为午夜时分) 的纪元秒为96163200。在该系统中,午夜表示一天的开始时刻。
让我们生成一个日期
通过perl中提供的gmtime函数,你可以自己来验证这点。给定一个用以表示自从纪元以来的秒数的整数,通过gmtime函数可以计算出代表相应的日期和时刻,例如:

perl –le print scalar gmtime 96163200

thu jan 18 00:00:00 1973

如果你调用 gmtime() 函数,你会得到一系列值的列表:

包括时,分,秒, 日期,月份,年份等等。

perl –le print join(",", gmtime 96163200)

0,0,0,18,0,73,4,17,0

前面3个0分别表示秒,分,时。小时是从0-23,故下午是12时往后。第4个数表示该月中的天数(本例中为18号)。第5个数表示月份,从0开始(代表1月份)。之所以从0开始,是因为月份对应着月份数组的下标:

@months = qw(jan feb mar apr may jun
     jul aug sep oct nov dec); $month  =
(gmtime 96163200)[4];     # "jan"

年份 (本例中为73)的表示有点特殊。它并不是年份的最后两位数字。它表示从1900年开始的年份。为什么要这样表示呢?这是因为 c语言就是这样处理的。perl试图使得其库和系统调用尽量接近操作系统的处理方式。

所以,如果你想输出4位数的年份,表示如下:

$year = (gmtime 96163200)[5] + 1900;

如果你不了解这种处理方式,就会制造出y2k问题,你也许会这样写:

$year = "19" . (gmtime 96163200)[5];

     # 出错!  2000年将变为19100

对于gmtime()函数的返回值还没有介绍完,还有4, 17, 和 0这3个数。它们分别表示一星期中的第几天 (星期日为0),一年中的第几天(0 表示一年中的第一天), 以及是否采用夏时制(表示不采用,正数表示采用,负数表示不可知)。
现在!现在!现在!
perl中的time() 函数返回以纪元秒形式表示的当前日期和时间。如果你打算把它转换为字符串,就可使用gmtime() 和localtime() 函数:

$now = localtime(time());
($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime(time());

如果调用 localtime() 或gmtime() 时不带参数,它将自己调用time()

$now = localtime();
($sec, $min, $hour, $day, $mon, $year, $wday, $yday, $isdst) = localtime();
常见的日期和时间操作
如果你打算计算两个时刻之间的时间段,只需将它们转换为相应的纪元秒,然后两数相减即可:

$difference_in_seconds = $later_datetime —
$earlier_datetime;

要把秒转换为分,时,或天数,只需要分别将它们除以60, 3600 和 86400 即可:

$difference_in_minutes = $difference_in_seconds / 60;
$difference_in_hours = $difference_in_seconds / 3600;
$difference_in_day = $difference_in_seconds / 86400;

反过来做,你也可以回答如下问题:“4天后是几号?”:

$then = time() + 86400 * 4;
print scalar localtime $then;

它给出的答案精确到秒。例如,如果4天后的纪元秒值为932836935, 你可以输出日期的字符串如下;

sat jul 24 11:23:17 1999

如果你打算输出那个日期的午夜时分 (如“sat jul 24 00:00:00 1999”) 使用如下模块:

$then = $then — $then % 86400;

     # 去掉那个日期的尾巴

类似地,你可以用四舍五入法,输出最靠近午夜时分的日期:

$then += 43200;    # add on half a day
$then = $then — $then % 86400;
     # truncate to the day

如果你的时区距离gmt为相差偶数个小时,这就管用了。并不是所有的时区都是很容易处理的。你所真正需要的是在你自己的时区内计算纪元秒,而不是在gmt中计算。

perl 中的名为time::local的模块,可以提供两个函数 timelocal() 和timegm()。其返回值同 localtime() 和gmtime() 一样。

use time::local;
$then = time() + 4*86400;
$then = timegm localtime $then;
# local epoch seconds
$then -= $then % 86400;
# truncate to the day
$then = timelocal gmtime $then;
     # back to gmt epoch seconds
print scalar localtime $then, "\n";
日常生活所用的日期和时间的表示
你已经级掌握了时,分,年等值的含义,也了解了纪元秒的含义。而日常生活中的日期和时间是用字符串来表示的,你怎样才能把日常所用的日期和时间串格式转换成纪元秒呢?

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

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";

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

     or die "not a date";

$mday = $1;

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

     "bad month";

$year = $3 — 1900;

($h, $m, $s) = ($4, $5, $6);

$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, "\n";

2147483647

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

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

tue jan 19 03:14:07 2038

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

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

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。
总结
不同的国家在不同的时期采用了罗马历法,你应该注意你使用的日期是采用的是什么历法。

在unix机器内部,每过1秒,纪元秒的计数器加1,如果该值是以32位有符号整数格式表示的,系统在2038年的日期将会出现翻转现象,预计大多数操作系统将在2038年之前改正这一问题。

对于在1902-2037范围内的日期和时期表示, 把它们转换为纪元秒,要存取这些数,你只需使用整数算术运算,gmtime() 和 localtime()函数,以及标准的time::local模块。如果要对该范围以外的日期进行计算或者要分析某特殊的日期格式,你可以使用cpan中的date::manip 和date::calc模块。

进一步的阅读

perl cookbook的第三章谈论了日期和时间, perlfunc 手册( 或programming perl的第三章) 介绍了gmtime() 和localtime() 函数。. cpan是指perl综合网。








文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
相关主题
文章页数:[1] 
Google
热门文章
·LB5000XP论坛配合SERV-U获取系统管理员权限-CGI教程,CGI文档
·CGI 版本-PHP教程,其它文章
·获取随机的由大小写字母和数字组成的八位密码-CGI教程,CGI文档
·Perl在NT下的快速简便安装方法 (转)-CGI教程,CGI文档
·实战 FastCGI(转)二-CGI教程,CGI文档
·XML和现代CGI应用程序-.NET教程,XML应用
·perl在win32平台上直接操作打印机-CGI教程,CGI文档
·实战 FastCGI(转)五(完)-CGI教程,CGI文档
·Python 快速入门(一)-CGI教程,CGI文档
·网站 PAGEVIEW 分析系统 CGI (原创)-CGI教程,CGI文档

最新文章
·顺便说说一些指示代码
·跟我学Perl(二)
·跟我学Perl(一)
·CGI教程(5)利用CGI解码FORM
·CGI教程(4)HTML 表单
·CGI教程(3)怎样发回文档给客户端
·CGI教程(2)怎样从服务器获得信息
·CGI教程(1)简介
·CGI教程(目录)
·Perl直接入门详尽指南




版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!

特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
  打印  刷新  关闭
返回首页 |关于我们 | 联系我们 | 付款方式 | 创业联盟 | 虚拟主机 | 资讯中心 | 友情链接 | 网站地图

版权所有 西部数码(www.west263.com)
CopyRight (c) 2002~2006 west263.com all right reserved.
公司地址:四川成都市万和路90号天象大厦4楼 邮编:610031
电话总机:028-86262244 86263048 86263408 86263960 86264018 86267838
售前咨询:总机转201 202 203 204 206 208
售后服务:总机转211 212 213 214
财务咨询:总机转224 223 传真:028-86264041 财务QQ:点击发送消息给对方635483282
售前咨询QQ:点击发送消息给对方2182518 点击发送消息给对方241975952 点击发送消息给对方275026793 点击发送消息给对方408235859
售后服务QQ:点击发送消息给对方17708515 点击发送消息给对方307742704 点击发送消息给对方287976517 点击发送消息给对方363783715
《中华人民共和国增值电信业务经营许可证》编号:川B2-20030065号