【问题标题】:Fractional part of epoch纪元的小数部分
【发布时间】:2015-05-04 15:27:47
【问题描述】:

我有一个 1372252864.901871 的纪元值,需要在 perl 中转换为本地时间。我知道 $val 设置为 1372252864.901871 的 localtime($val) 会将值转换为本地时间。但我还需要为此添加 100 毫秒或 86.7 毫秒的值并确定计算的本地时间。我该怎么做呢?函数 localtime() 是否处理我给出的小数时期值?

【问题讨论】:

    标签: perl perl-module perl-data-structures


    【解决方案1】:

    如果您只想添加到一个纪元时间并获得另一个纪元时间,只需执行以下操作:

    1372252864.901871 + .0867
    

    如果您正在做其他事情,不,本地时间不会保留小数秒。您可能想使用 DateTime 来处理小数秒:

    use DateTime;
    my $time = DateTime->from_epoch(epoch=>1372252864.901871, time_zone=>'local');
    $time->add(nanoseconds=>86.7e6);
    print $time->epoch + $time->nanosecond / 1e9;
    

    (此示例不需要 time_zone,但听起来您可能希望使用此时间做的其他事情)

    【讨论】:

      【解决方案2】:

      你可能想要Time::HiRes:

      Time::HiRes 模块为 usleep 实现了一个 Perl 接口, nanosleep、ualarm、gettimeofday 和 setitimer/getitimer 系统调用, 换句话说,高分辨率时间和计时器

      【讨论】:

      • 我认为Time::HiRes 不能满足 OP 的要求。他已经有了一个高分辨率的时间值1372252864.901871。他想将其分解为年、月、...、秒,并以高分辨率显示秒。
      • 没错。 Time::HiRes 不适合我。我需要将时代转换为年-月-日-秒-毫秒分辨率。然后我需要为此添加 x 毫秒的值。是否有任何函数可以将值添加到本地时间?
      • 我认为您可能使问题过于复杂。由于纪元日期以秒为单位,而高分辨率值以小数秒为单位,请将 x 毫秒除以我的 1000 将 x 小数秒转换为 x 小数秒。将其添加到您现有的小数秒中,鲍勃是你的叔叔?
      • 换句话说 - 保持小数时代形式的时间 - 在需要使用它进行显示之前不要转换为本地时间列表。
      • 您只需要将纪元值转换为日期/时间字段,还是需要对当前时区进行更正?另外,你说你想要Year-Month-Day-Secs-Millisecs。不是小时和分钟?
      【解决方案3】:

      localtime 函数将像 1372252864 这样的原始时间分解为年、月、日等。原始时间的任何小数部分都会被忽略。

      我不知道有任何功能,无论是内置的还是模块中的,都支持分辨率小于 1 秒的分解时间。

      但既然你已经有了小数秒,我想说你已经可以做你需要做的事情了。只需使用localtime(或gmtime)分解原始时间戳的整数部分,然后取小数部分:

      $timestamp = 1372252864.901871;
      @parts = localtime($timestamp);
      $fraction = $timestamp - int($timestamp);
      $milliseconds = int($fraction * 1000.0);
      

      编写您自己的高分辨率替换 localtime 应该很容易,它会为您执行此操作。

      如果您需要将 86.7 毫秒添加到时间戳,则无论如何您都需要使用原始格式:

      $timestamp = 1372252864.901871;
      $timestamp += 86.7/1000.0;
      

      【讨论】:

        【解决方案4】:

        我想到的最简单的方法是使用Time::HiRes::Value 处理精度为 1μs 的运算,并使用Time::Piece 将结果格式化为日期/时间字符串。

        Time::HiRes::Value 将时间保存为一个二元素数组;第一个字段包含整秒,而第二个字段包含微秒数。这与 Time::HiRes 函数使用的格式相同,但我所知道的没有任何东西会本机转换为日期/时间字符串,所以我使用 Time::Piece 转换整个秒数并附加小数秒。

        看起来像这样

        use strict;
        use warnings;
        
        use Time::HiRes::Value;
        use Time::Piece;
        
        my $dt    = Time::HiRes::Value->new(1372252864.901871);
        my $delta = Time::HiRes::Value->new(86.7E-3); # 86.7ms
        $dt += $delta;
        print dt_to_string($dt), "\n";
        
        sub dt_to_string {
          my ($dt) = @_;
          Time::Piece->new($dt->[0])->datetime =~ s{(\d+)\z}{$1 + $dt->[1] / 1E6}er;
        }
        

        输出

        2013-06-26T14:21:4.98857
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-11-25
          • 2017-10-13
          • 2013-07-21
          • 2013-04-24
          • 2010-09-13
          • 2011-11-07
          • 2018-05-28
          相关资源
          最近更新 更多