我有一个包含以这种格式包含日期字符串的数据的文件:
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。
答案 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";
享受吧!