需要将数据转换为Excel可读格式

时间:2012-07-06 20:51:14

标签: perl excel cygwin

我有一个包含以这种格式包含日期字符串的数据的文件:

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

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

目的/期望的最终结果是时间&我可以在Excel中进行简单数学处理的日期戳(即通过时间戳记获得条目之间的年龄差异)。

为此,我希望最终看到这样的日期戳:

6/11/2012 3:47:56 PM

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

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

我在cpan中查找了模块时间:: piece,但是并不是真的理解它。我在一个Cygwin高管中工作,所以不是一个真正的unix系统,并且没有太多的手册页或perldocs。

5 个答案:

答案 0 :(得分:1)

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

Formatting dates with strftime really cool article

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;
祝你好运!

答案 1 :(得分: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

答案 2 :(得分: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的模块文档。 它最适合解析非常统一的输入数据。遇到最轻微的偏差,模块不会解析它(你可以解决这个问题)

答案 3 :(得分: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的未来之路,所以你最好得到use to it

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

当我这样做时:

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

我正在创建一个名为Time::Piece的{​​{1}}对象(nee容器),用于存储时间。

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

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

您可以使用Unix %d命令来使用这些格式:

date

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

$ 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 TIME )方法(nee子例程)与{{1}相反}。这需要花费时间(在strftime中,并以您指定的格式返回时间。

答案 4 :(得分:0)

如果您在安装新的额外软件包时遇到问题,则可以使用Plain Per来完成。获得Excel日期序列值(例如61,59340278)后,您可以使用Excel在自定义日期中格式化该数字的外观。

例如:

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

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

as> 1900.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";

享受吧!