Perl 日期和时间
Perl - 日期与时间操作
Section titled “Perl - 日期与时间操作”Perl 提供了内置函数用于基本的日期和时间操作。对于更复杂的任务,强烈推荐使用强大的模块,如 Time::Piece(Perl 5.10 起的核心模块)以及 DateTime(来自 CPAN)。
获取当前日期和时间
Section titled “获取当前日期和时间”localtime() 函数是获取当前本地日期和时间的主要方式。不带参数时,它使用当前的系统时间。
在列表上下文(list context)中,localtime() 返回一个包含 9 个元素的列表:
# 元素 描述 范围# -------------------------------------------------------# $sec 秒 0-60 (60 用于闰秒)# $min 分 0-59# $hour 小时 0-23# $mday 月份中的日期 1-31# $mon 月份 0-11 (0 表示一月)# $year 自 1900 年起的年份 (例如,2023 年是 123)# $wday 星期几 0-6 (0 表示星期日)# $yday 年份中的日期 0-365 (365 用于闰年)# $isdst 夏令时标志 (如果夏令时生效则为真)在列表上下文(list context)中使用 localtime() 的示例:
#!/usr/bin/env perluse strict;use warnings;
my @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);my @days = qw(Sun Mon Tue Wed Thu Fri Sat);
my ($sec, $min, $hour, $mday, $mon, $year_offset, $wday, $yday, $isdst) = localtime();
my $year = 1900 + $year_offset;
print "Date: $days[$wday], $months[$mon] $mday, $year\n";print "Time: $hour:$min:$sec\n";print "Day of year: $yday\n";print "DST in effect: ", ($isdst ? "Yes" : "No"), "\n";执行时,可能会产生如下输出(取决于当前的日期/时间):
Date: Sat, Feb 16, 2024Time: 14:30:55Day of year: 46DST in effect: No在标量上下文(scalar context)中,localtime() 返回一个人类可读的字符串:
#!/usr/bin/env perluse strict;use warnings;
my $datestring = localtime();print "Current local date and time: $datestring\n";输出:
Current local date and time: Sat Feb 16 14:30:55 2024GMT/UTC 时间
Section titled “GMT/UTC 时间”gmtime() 函数的功能与 localtime() 完全相同,但它返回的时间组件是格林威治平均时间 (GMT) 或协调世界时 (UTC) 时区本地化的。gmtime() 在列表上下文(list context)中的 $isdst 元素始终为 0,因为 GMT/UTC 不遵守夏令时。
#!/usr/bin/env perluse strict;use warnings;
my $gmt_datestring = gmtime();print "Current GMT/UTC date and time: $gmt_datestring\n";
my (undef, undef, undef, $mday, $mon, $year_offset) = gmtime();my $year = 1900 + $year_offset;printf "GMT Date: %04d-%02d-%02d\n", $year, $mon + 1, $mday;输出(假设本地时间为美国中部时间,比 UTC 晚 6 小时):
Current GMT/UTC date and time: Sat Feb 16 20:30:55 2024GMT Date: 2024-02-16格式化日期和时间
Section titled “格式化日期和时间”您可以结合 printf 或 sprintf 使用 localtime() 或 gmtime() 返回的元素进行自定义格式化:
#!/usr/bin/env perluse strict;use warnings;
my ($sec, $min, $hour, $mday, $mon, $year_offset) = localtime();my $year = 1900 + $year_offset;$mon += 1; # 将月份调整为 1-12
printf("Formatted Time (HH:MM:SS): %02d:%02d:%02d\n", $hour, $min, $sec);printf("Formatted Date (YYYY-MM-DD): %04d-%02d-%02d\n", $year, $mon, $mday);输出:
Formatted Time (HH:MM:SS): 14:30:55Formatted Date (YYYY-MM-DD): 2024-02-16纪元时间(Unix 时间戳)
Section titled “纪元时间(Unix 时间戳)”time() 函数返回自 Unix 纪元(UTC 1970 年 1 月 1 日 00:00:00)以来经过的秒数。这通常被称为 Unix 时间戳。
#!/usr/bin/env perluse strict;use warnings;
my $epoch_seconds = time();print "Seconds since Jan 1, 1970 UTC: $epoch_seconds\n";
# 您可以将纪元时间戳传递给 localtime() 或 gmtime()my $one_day_ago_epoch = $epoch_seconds - (24 * 60 * 60);my $datestring_one_day_ago = localtime($one_day_ago_epoch);print "One day ago: $datestring_one_day_ago\n";输出:
Seconds since Jan 1, 1970 UTC: 1708093855One day ago: Fri Feb 15 14:30:55 2024POSIX strftime() 函数
Section titled “POSIX strftime() 函数”为了更灵活的格式化,POSIX 模块提供了 strftime() 函数。它根据一个格式字符串格式化日期和时间,类似于同名的 C 标准库函数。
strftime(format, sec, min, hour, mday, mon, year, wday (可选), yday (可选), isdst (可选))
常用的 strftime() 格式说明符(与区域设置相关的用 * 标记):
| 说明符 | 描述 | 示例(针对 Sat Feb 16 14:30:55 2024 CST) |
|---|---|---|
| %a | 缩写星期名称 * | Sat |
| %A | 完整星期名称 * | Saturday |
| %b | 缩写月份名称 * | Feb |
| %B | 完整月份名称 * | February |
| %c | 区域设置对应的日期和时间表示 * | Sat Feb 16 14:30:55 2024 |
| %C | 世纪(年份除以 100 并截断为整数) | 20 |
| %d | 月份中的日期,零填充 (01-31) | 16 |
| %D | 简短的月/日/年格式,等同于 %m/%d/%y | 02/16/24 |
| %e | 月份中的日期,空格填充 ( 1-31) | 16 |
| %F | ISO 8601 日期格式 (YYYY-MM-DD),等同于 %Y-%m-%d | 2024-02-16 |
| %g | 基于周的年份,最后两位数字 (00-99) | 07 |
| %G | 基于周的年份 (例如,2024) | 2024 |
| %h | 缩写月份名称 * (与 %b 相同) | Feb |
| %H | 24 小时制的小时 (00-23) | 14 |
| %I | 12 小时制的小时 (01-12) | 02 |
| %j | 年份中的日期,零填充 (001-366) | 047 |
| %m | 月份的十进制表示,零填充 (01-12) | 02 |
| %M | 分钟,零填充 (00-59) | 30 |
| %n | 换行符 | \n |
| %p | 12 小时制的 AM 或 PM 标记 * | PM |
| %r | 12 小时制时间 * (例如,hh:mm:ss AM/PM) | 02:30:55 PM |
| %R | 24 小时制 HH:MM 时间,等同于 %H:%M | 14:30 |
| %S | 秒,零填充 (00-60) | 55 |
| %t | 水平制表符 | \t |
| %T | ISO 8601 时间格式 (HH:MM:SS),等同于 %H:%M:%S | 14:30:55 |
| %u | ISO 8601 星期几编号 (星期一=1, 星期日=7) | 6 |
| %U | 年份中的周数(以星期日作为一周的第一天)(00-53) | 07 |
| %V | ISO 8601 年份中的周数(以星期一作为一周的第一天)(01-53) | 07 |
| %w | 星期几的十进制表示 (星期日=0, 星期六=6) | 6 |
| %W | 年份中的周数(以星期一作为一周的第一天)(00-53) | 07 |
| %x | 区域设置对应的日期表示 * | 02/16/24 |
| %X | 区域设置对应的时间表示 * | 14:30:55 |
| %y | 年份,后两位数字 (00-99) | 24 |
| %Y | 年份 (例如,2024) | 2024 |
| %z | ISO 8601 时区与 UTC 的偏移量 (例如,+hhmm 或 -hhmm) | -0600 |
| %Z | 时区名称或缩写 * | CST |
| %% | 字面量 % 字符 | % |
使用 POSIX::strftime() 的示例:
#!/usr/bin/env perluse strict;use warnings;use POSIX qw(strftime);
my @time_parts = localtime(); # 获取当前的本地时间组件# 注意:strftime 期望年份为 (当前年份 - 1900)# 并且月份为 0-11,localtime() 直接提供这些值。
my $formatted_string = strftime "%Y-%m-%d %H:%M:%S %Z (%A)", @time_parts;print "Formatted local time: $formatted_string\n";
my @gmt_time_parts = gmtime();my $gmt_formatted_string = strftime "%Y-%m-%dT%H:%M:%SZ (%A)", @gmt_time_parts;print "Formatted GMT/UTC time: $gmt_formatted_string\n";输出:
Formatted local time: 2024-02-16 14:30:55 CST (Saturday)Formatted GMT/UTC time: 2024-02-16T20:30:55Z (Saturday)现代日期和时间模块
Section titled “现代日期和时间模块”Time::Piece(核心模块):
Section titled “Time::Piece(核心模块):”自 Perl 5.10 起,Time::Piece 已成为一个核心模块,提供了一种面向对象的日期和时间操作方法,通常比原始的 localtime/gmtime 和 strftime 更易于使用。
#!/usr/bin/env perluse strict;use warnings;use Time::Piece;use Time::Seconds; # 用于像 ONE_DAY 这样的常量
my $t = localtime(); # 为当前本地时间创建一个 Time::Piece 对象
print "Current time: ", $t->datetime, "\n"; # YYYY-MM-DDTHH:MM:SSprint "Formatted: ", $t->strftime("%A, %B %d, %Y, %I:%M %p"), "\n";print "Epoch seconds: ", $t->epoch, "\n";
my $tomorrow = $t + ONE_DAY;print "Tomorrow: ", $tomorrow->date, "\n"; # YYYY-MM-DD
my $custom_time = Time::Piece->strptime("2023-07-15 10:00:00", "%Y-%m-%d %H:%M:%S");print "Custom time: ", $custom_time->strftime("%c"), "\n";DateTime(CPAN 模块):
Section titled “DateTime(CPAN 模块):”对于更高级的日期/时间操作,包括复杂的时区处理、日期算术、解析各种格式以及国际化,来自 CPAN 的 DateTime 模块套件是 Perl 社区事实上的标准。它功能非常强大且全面。
#!/usr/bin/env perluse strict;use warnings;use DateTime;
my $dt = DateTime->now(time_zone => 'local'); # 当前本地时间print "DateTime now: ", $dt->iso8601, " (", $dt->time_zone_long_name, ")\n";
my $dt_ny = DateTime->now(time_zone => 'America/New_York');print "New York time: ", $dt_ny->strftime('%Y-%m-%d %H:%M:%S %Z'), "\n";
$dt->add(days => 5, hours => 3);print "After adding 5 days, 3 hours: ", $dt->datetime, "\n";
# 需要使用 'cpanm DateTime' 或类似命令进行安装。建议:对于新项目,考虑到更高的清晰度、健壮性和更丰富的功能集,对于简单的任务优先使用 Time::Piece,对于更复杂的需求使用 DateTime,而非使用较旧的过程式函数。