【问题标题】:Perl Localtime Returning 16 Hours When Input is only Seconds当输入仅为秒时,Perl 本地时间返回 16 小时
【发布时间】:2011-06-12 14:43:31
【问题描述】:

我一定是做错了什么,但我想不通。当我将秒作为 localtime() 的参数时,我得到秒和 16 小时。

my $startTime = time;

(process)

my $endTime = time;

my $diffTime = ( $endTime - $startTime );

($sec,$min,$hour) = localtime( $diffTime );

print STDERR "diffTime = $diffTime\n";
print STDERR "hour = $hour\n";
print STDERR "min= $min\n";
print STDERR "sec = $sec\n";

print( sprintf( "Elapsed time : %02d:%02d:%02d\n", $hour, $min, $sec ) );

...总是打印:

diffTime = 4
hour = 16
min= 0
sec = 4
Elapsed time : 16:00:04

好的。想出了如何添加 cmets - NoScript 设置太紧了。

谢谢...

我似乎无法在此线程中添加 cmets,所以我只是在这里感谢大家。

不使用 gmtime 是问题所在。它可能不是最有效的解决方案,但它可以满足我的需要,这只是用户评估他/她可能等待例程完成多长时间并决定输入的大小的简单信息他/她熟悉的数据集。

【问题讨论】:

  • 嗯,你不会碰巧在格林威治标准时间,是吗?如果不是,您会看到根据您的本地时区的变化。

标签: perl time localtime elapsed


【解决方案1】:

您正在混合持续时间和时间戳,这是自找麻烦... 你可能像 Mansoor 建议的那样,使用 gmtime 侥幸成功,但你还是把苹果当作橘子。

以下工作,并使用核心 Time::PieceTime::Seconds 模块。不过,对于$diffTime->pretty,您需要比当前版本的 Perl 捆绑的 Time::Piece 更新版本 (1.20)。

use strict;
use warnings;
use 5.010;
use Time::Piece 1.20;

my $startTime = localtime();

# (process)

my $endTime = localtime();

my $diffTime = ( $endTime - $startTime );

say STDERR "diffTime = ", $diffTime;
say STDERR "hours = ", $diffTime->hours;      # not the same thing as above
say STDERR "minutes = ", $diffTime->minutes;  # not the same thing as above
say STDERR "seconds = ", $diffTime->seconds;  # not the same thing as above

say "Elapsed time: ", $diffTime->pretty;

这可能会打印如下内容:

150
0.0416666666666667
2.5
150
2 minutes, 30 seconds

【讨论】:

  • “你可能侥幸逃脱”部分是错误的。其余的都是对的。
  • @tchrist:他为什么不侥幸逃脱呢?只要他的过程不超过 86400 秒,他就会得到他期望的输出,不是吗?
  • 我非常感谢这里的所有回复,我希望我能在未来贡献一些答案。
  • Elapsed times 永远不应包含“1970”或“2010”之类的内容,并且假装它不存在于 gmtimelocaltime 返回值中是具有欺骗性和误导性的。这就像说对2**2 使用加法而不是求幂“可能”会得到正确的答案。
【解决方案2】:

$difftime 是两个“纪元时间”(自 1970 年 1 月 1 日格林威治标准时间午夜以来的秒数)之间的差异,但这并不能使其成为纪元时间。所以这对于localtime() 来说并不是一个真正合适的论据。您最好自己计算 h/m/s 细分:

($sec,$min,$hour) = ($difftime % 60, int($difftime/60) % 60, int($difftime/3600));

【讨论】:

  • 这可能是最好的解决方案。我知道使用 gimtime 很麻烦。
【解决方案3】:

您想使用gmtime 函数而不是localtime 函数。

由于纪元日期是 1970 年 1 月 1 日 00:00:00 GMT/UTC,调用 localtime(0) 将为您提供您的时区中的纪元日期.

编辑:感谢您的跟进。如前所述,这仅在您测量的间隔小于 24 小时时才有效。 localtimegmtime 函数实际上都返回日期的值:秒、分钟、小时、月中的某天、月、年、年中的某日,以及时间是否属于夏令时。当然,除了日期的上下文之外,秒、分钟和小时之外的所有内容都没有意义。

【讨论】:

  • 这不是问题的答案。
  • tchrist:你是​​说切换到gmtime 不会解决问题吗?我认为只要时间跨度不到一个月,它应该可以正常工作。
  • ($sec,$min,$hour)=gmtime($difftime) 有效,但只是偶然。
【解决方案4】:

这与说因为 ℉ → ℃ 需要转换 C = (F - 32) * 5/9 是同一个问题,如果它变暖了 5 ℉ 那必须与变热 -15 ℃ 相同,因为那是你的数字只需将 5 ℉ 代入明显但错误的公式即可。

明白为什么这没有意义吗?升温 5 ℉ 与降温 15 ℃ 完全不同!

你的时代也犯了同样的错误。当您减去每个测量自纪元以来经过的秒数的量时,您确实不会得到同样测量自纪元以来经过的秒数的结果!

您只能在纪元秒上调用localtimegmtime,这意味着自纪元以来经过的秒数,而不是一般的秒数。否则,您必须自己进行除法,或者使用模块来找出减法的结果中有多少更大的单位。

【讨论】:

  • 虽然我原则上同意你的观点,但反对“但它有效”需要一个反例。
  • 反例是任何耗时 86400 或更多秒的任务。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-22
  • 2019-10-05
  • 2019-10-17
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多