1

我有一个文件,其中包含这种格式的日期字符串:

June 11, 2012 3:47:56 PM GMT-07:00

我已经在使用 Perl 脚本来操作该文件中的一些其他数据元素,然后将其作为 Excel 的 csv 输出。我认为我应该能够在 Perl 中更轻松/更快地完成它,而不是在 Excel 中使用函数和公式来尝试将日期作为字符串转换为 Excel 可以读取的内容。

目的/期望的最终结果是一个时间和日期戳,我可以在 Excel 中进行简单的数学运算(即,通过计算时间戳来获取条目之间的年龄差异)。

为此,我希望我的日期戳看起来像这样:

6/11/2012 3:47:56 PM

真的我只需要转换日期,时间是完美的,并删除GMT差异垃圾。

我已经看到代码片段和对模块的引用似乎以另一种方式转换......即,从“2012 年 6 月 24 日”到“2012 年 6 月 24 日”,但这对我来说是错误的方向。

我在cpan中查找了module time::piece,但不太明白。我在 Cygwin exec 中工作,所以不是真正的 unix 系统,并且没有太多的手册页或 perldocs。

4

5 回答 5

1

您可以使用模块Date::Parse和 POSIX 函数strftime。CPAN中有很多模块可以解析日期。

用 strftime 格式化日期真的很酷的文章

use strict;
use Date::Parse;
use POSIX qw/strftime/;

my $time = str2time( 'June 11, 2012 3:47:56 PM GMT-07:00' );
my $date = strftime "%m/%d/%Y %H:%M:%S %p", localtime($time);
print $date;

祝你好运!

于 2012-07-06T22:28:30.533 回答
0

如果您的原始字符串是:$timestring,那么这应该可以工作(未经测试):

my %months = (January => '1', February =>'2', March => '3', ...); 

...

等等

$timestring =~ s<^(w+)\x20(\d{1,2}),\x20(\d{4})(\x20\(?:\d{1,2}\:){2}\d{1,2}\x20PM).*$><"$months{$1}/$2/$3$4">eeg
于 2012-07-07T00:41:29.610 回答
0
use DateTime;
use DateTime::Format::Strptime;

# YOU MUST ADAPT THIS PATTERN
my $pat = "%b %d, %Y"; #incomplete
my $d  = DateTime::Format::Strptime->new( pattern => $pat, on_error => 'croak' );
my $dt = $d->parse_datetime($strdate);

say $dt->mdy("/") . " "  . $dt->hms(":") . " " . $dt->am_or_pm;

但请注意,Excel 更喜欢 ISO 格式的日期时间类型:

say $dt->ymd('-') . 'T' . $dt->hms(':');

要微调模式 $pat,请阅读DateTime::Format::Strptime的模块文档。它最适合解析非常统一的输入数据。遇到最轻微的偏差,模块不会解析它(不过你可以解决这个问题)

于 2012-07-07T21:39:27.520 回答
0

许多人都有他们最喜欢的时间解析技术。我喜欢Time::Piece,因为它带有 Perl(至少任何超过 5.10 的版本):

my $time_string = "June 11, 2012 3:47:56 PM GMT-7:00";
my $time_string =~ / GMT.*$//;  # That "GMT-7:00" messes things up!
say $time_string   # June 11, 2012 3:47:56 PM GMT

my $time = Time::Piece->strptime(
    $time_string, "%B %d, %Y %l:%M:%S %p" );

say $time->strftime("%D %l:%M:%S %p");

面向对象的$foo->bar编码风格正在成为 Perl 的未来方式,所以你最好习惯

这并不是真的那么复杂。基本上,您创建一个包含所有数据的容器。哈希可以保存各种信息的方式。

当我这样做时:

my $time = Time::Piece->strptime( "$time_string", "$time_format" );

我正在创建一个名为存储时间的Time::Piece对象(nee 容器) 。$time

当您说 时$time->Weekday,您实际上是在执行一个名为的子例程Weekday,它获取您的$time 容器,从中提取信息,解析时间,并返回工作日。

( STR ing P ass TIME )构造函数strptime(它是创建容器的函数)正在获取您的时间字符串(第一个参数)和它的格式(第二个参数)并创建该对象。各种和指定的特定时间字段。这些可以在strptime联机帮助页中找到。$time%M%d

您可以使用 Unixdate命令来处理这些格式:

$ date "+%m/%d/%y"
08/23/13
$ date "+%m/%d/%Y"
08/23/2013
$ date "%Y-%m-%d"
2013-08-23

这可能会让你对他们感觉更舒服。

( STR ing F ormat TIMEstrftime ) 方法(nee 子程序)与. 这需要时间(以您指定的格式输入并返回时间。strptime$time

于 2013-08-23T19:48:20.500 回答
0

如果您在安装新的额外软件包时遇到问题,您可以使用 plain per 来完成。一旦您有了 Excel 日期序列值,例如 61,59340278,您就可以使用 Excel 在自定义日期中格式化该数字的外观。

例如:

61,59340278 使用自定义日期格式显示在 Excel 中

自定义单元格格式:TT.MM.JJJJ hh:mm:ss

如> 01.03.1900 14:14:30

下面的函数

sub date2excelvalue {
  my($day1, $month, $year, $hour, $min, $sec) = @_;
  my @cumul_d_in_m = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365);
  my $doy = $cumul_d_in_m[$month - 1] + $day1;

  #
  full years + your day
  for my $y(1900..$year) {
    if ($y == $year) {
      if ($month <= 2) {

        #
        dont add manually extra date
        if inJanuary or February
        last;
      }
      if ((($y % 4 == 0) && ($y % 100 != 0)) || ($y % 400 == 0) || ($y == 1900)) {
        $doy++;#
        leap year
      }
    } else {#
      full years
      $doy += 365;
      if ((($y % 4 == 0) && ($y % 100 != 0)) || ($y % 400 == 0) || ($y == 1900)) {
        $doy++;#
        leap year
      }

    }
  }#
  end
  for y# calculate second parts as a fraction of 86400 seconds
  my $excel_decimaltimepart = 0;
  my $total_seconds_from_time = ($hour * 60 * 60 + $min * 60 + $sec);
  if ($total_seconds_from_time == 86400) {
    $doy++;#
    just add a day
  } else {#
    add decimal in excel
    $excel_decimaltimepart = $total_seconds_from_time / (86400);
    $excel_decimaltimepart = ~s / 0\. //;
  }
  return "$doy\.$excel_decimaltimepart";

}

sub excelvalue2date {
  my($excelvalueintegerpart, $excelvaluedecimalpart) = @_;
  my @cumul_d_in_m = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365);
  my @cumul_d_in_m_leap = (0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366);
  my @cumul_d_in_m_selected;
  my($day1, $month, $year, $hour, $min, $sec);
  $day1 = 0;#
  all days all years
  my $days_in_year;
  my $acumdays_per_month;
  my $daysinmonth;
  my $day;

  #
  full years + your day
  for my $y(1900. .3000) {
    my $leap_year = 0;#
    leap year
    my $leap_year_mask = 0;#
    leap year
    if ((($y % 4 == 0) && ($y % 100 != 0)) || ($y % 400 == 0) || ($y == 1900)) {
      $leap_year = 1;#
      leap year
      @cumul_d_in_m_selected = @cumul_d_in_m_leap;

    } else {
      $leap_year = 0;#
      leap year
      @cumul_d_in_m_selected = @cumul_d_in_m;
    }

    if (($day1 + (365 + $leap_year)) > $excelvalueintegerpart) {

      #
      found this year $y
      $year = $y;
      print "year $y\n";

      $days_in_year = $excelvalueintegerpart - $day1;
      $acumdays_per_month = 0;
      print "excelvalueintegerpart  $excelvalueintegerpart\n";
      print "day1  $day1\n";
      print "daysinyear $days_in_year\n";
      for my $i(0..$# cumul_d_in_m) {
        if ($i == $# cumul_d_in_m) {
          $month = $i + 1;#
          month 12 December
          $day = $days_in_year - $cumul_d_in_m_selected[$i];
          last;

        } else {

          if (($days_in_year > ($cumul_d_in_m_selected[$i])) && ($days_in_year <= ($cumul_d_in_m_selected[$i + 1]))) {
            $month = $i + 1;
            $day = $days_in_year - $cumul_d_in_m_selected[$i];
            last;
          }

        }

      }#
      end
      for $i months

      # end year
      last;

    } else {#
      full years
      $day1 += (365 + $leap_year);
    }

  }#
  end
  for years interger part comparator

  my $total_seconds_inaday;
  $total_seconds_inaday = "0\.$excelvaluedecimalpart" * 86400;

  $sec = $total_seconds_inaday;
  $hour = int($sec / (60 * 60));
  $sec -= $hour * (60 * 60);
  $min = int($sec / 60);
  $sec -= $min * (60);
  $sec = int($sec);
  return ($day, $month, $year, $hour, $min, $sec);

}
my $excelvariable = date2excelvalue(1, 3, 2018, 14, 14, 30);
print "Excel variable: $excelvariable\n";
my($integerpart, $decimalwithoutzero) = ($1, $2) if ($excelvariable = ~m / (\d + )\.(\d + ) / );
my($day1, $month, $year, $hour, $min, $sec) = excelvalue2date($integerpart, $decimalwithoutzero);
print "Excel Date from value: $day1, $month, $year, $hour, $min, $sec\n";

好好享受!

于 2018-10-26T13:05:44.827 回答