C语言中对时间和日期的处理

时间:2021-05-18 22:09:01
 
C语言中对时间和日期的处理
Chuck Allison
Chuck Allison 是盐湖城圣 Latter Day 教堂总部下耶稣教堂家族历史研究处的软件体系设计师。他拥有数学学士和数学硕士学位。他从1975年起开始编程,从1984年起他开始从事c语言的教学和开发。他目前的兴趣是面向对象的技术及其教育。他是X3J16,ANSI C ++标准化委员会的一员。 发送e-mail到allison@decus.org,或者拨打电话到(801)240-4510均可以与他取得联系。
大部分的操作系统有办法得到当前的日期和时间。通过定义在 time.h的库函数,ANSI C能以许多不同的形式得到这个信息。函数 time返回一个类型为 time_t的值(通常为long),该函数在运行期间对当前的日期和时间进行编码。然后你可以将这个返回值传递给其他能对该值进行解码和格式化的函数。
Listing 1中的程序使用函数 timelocaltimestrftime以不同的形式输出当前的日期和时间。函数 localtime把已经编码的时间解码成如下的struct:
 
 
 
 
 
 
 
 
 
 
 
 
每次当你调用localtime的时候,它会重写一个静态的结构并返回该结构的地址(因此同一时刻在一个程序中只能取得一个这样的结构,而不能做明显的拷贝)。函数ctime返回一个指向静态字符串的指针,该字符串以标准的格式包含了完整的时间和日期。strftime根据用户的指定格式格式化字符串(例如,%A代表一周中每一天的名称)。Table 1列出了格式描述符的完整列表。
时间/日期运算
通过改变 tm结构里的值,可对时间/日期进行运算。 Listing 2中的程序展示了如何计算将来某天的日期和以秒为单位所计算出的程序执行时间。注意函数 time的语法(参数 time_t由地址传入,并非作为函数的返回值)。函数 mktime改变 tm结构的值,以便日期和时间在一个合适的范围内,之后day-of-week ( tm_wday)和day-of-year ( tm_yday)域进行相应的更新。 mktimetm结构中日期和时间的值置于合适的范围之内,相应的更新day of week ( tm-wday)和day of year ( tm-yday)的值。这种情况发生在当一个日期超出了你的实现能够支持的范围的时候。例如,我的MS-DOS的编译器不能编码1970年1月份之前的日期。函数 asctime返回 tm参数所描述时间的标准字符串(因此 ctime (&tval)与as ctime (localtime(&tval)是相等的)。函数 difftime返回用秒做单位的两个 time_t的差。
如果需要处理超出系统范围的日期,或者需要计算两个日期的间隔又不是用秒来做单位,那你需要设计自己的date编码。 Listing 3Listing 5中的应用程序通过使用一个简单的month-day-year结构,展示了确定两个日期间隔的年数、月份数和天数的技术。日期的相减就像你在小学里做的减法那样(例如,首先进行天数的相减,如果需要就向月份数借位,以此类推)。注意跳过的年份都被计算进去了。为了简略起见, date_interval函数假设日期都是有效的,并且第一个日期在第二个日期之前。函数返回一个指向静态 Date结构的指针,该结构包含了我们想要的答案。
文件时间/日期戳
大多数操作系统为文件维护时间/日期戳。至少你能得知一个文件最后被修改的时间。(常用的 make工具使用这一信息来决定一个文件是否需要被重新编译,或者一个应用程序是否需要被重新连接)。由于文件系统在不同平台上有所不同,没有什么通用的函数得到一个文件的时间/日期戳,因此ANSI 标准没有定义这样的函数。然而,大多数流行的操作系统(包括MS-DOS和VAX/VMS)提供了UNIX函数 stat,该函数返回相关的文件信息,包括用 time_t表示的最后修改时间。
Listing 6中的程序使用 statdifftime来确定是否 time1.ctime2.c更新(例如,是否最近被修改过)。
如果你需要更新一个文件的时间/日期戳到当前时间,可简单的重写文件的第一个字节。虽然实际内容并未改变,但你的文件系统会认为文件已经被改变了,并且会相应的更新时间/日期戳。(知道你的文件系统!在VAX/VMS下,当你得到一个文件的新版本的时候,旧的版本仍会被保留)。这种技术叫做“‘touching’一个文件”。 Listing 7touch的实现在指定文件不存在的时候会创建一个新文件。注意文件以“binary”模式打开(在打开模式字符串中由字符 b决定—在将来的专栏中我会详细讨论文件处理的问题)。
表1:strftime的格式描述符
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


 
 
 
 
 
Listing 1 time1.c — 采用不同格式输出当前的日期和时间
 
 
 
 
 
 
 
 
 
 
 
 
 


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


 
 
 
 
 
 
 
 
 
Listing 2 time2.c —展示如何计算将来某一天的日期以及以秒为单位计算出的执行时间
 
 
 
 
 
 
 
 
 


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


 
 
 
 
 
 
 
 
 
Listing 3 date.h — 一个简单的日期结构
 
 
 
 
 
 
 
 
 


Listing 4 date_int.c — 计算两个日期的间隔
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


 
 
 
 
 
 
 
 
 
 
 
 
 
Listing 5 tdate.c — 举例说明日期间隔函数的使用
 
 
 
 
 


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


 
 
 
 
 
 
 
 
 
 
Listing 6 ftime.c — 确定是否time1.c比time2.c更新
 
 
 
 
 
 
 
 


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Listing 7 touch.c —通过覆盖旧文件或者创建一个新的文件来更新时间戳