所有
我想知道从给定日期开始的上周三的日期。
EG。我的日期是" 20150804"我需要" 20150729"。
DateTime不可用,我也无法安装。
我查看了一些示例,但他们使用的是DateTime。
请你重新定位我可以获得帮助的地方。感谢。
我打算编写类似下面的代码。
代码:
#!/opt/perl-5.8.0/bin/perl
use warnings;
use strict;
my $dt="20150804";
my $prevWednesday=getPrevWednesday($dt);
sub getPrevWednesday()
{
my $givenDt=shift;
...
}
答案 0 :(得分:5)
另一种蛮力方法,这次使用另一个核心模块Time::Local。
#!/usr/bin/perl
use warnings;
use strict;
use Time::Local;
sub prev_wednesday {
my $date = shift;
my ($year, $month, $day) = $date =~ /(....)(..)(..)/;
my $time = timelocal(0, 0, 12, $day, $month - 1, $year);
do { $time -= 60 * 60 * 24 } until (localtime $time)[6] == 3; # <- Wednesday
my ($y, $m, $d) = (localtime $time)[5, 4, 3];
return sprintf "%4d%02d%02d\n", 1900 + $y, $m + 1, $d;
}
print $_, ' ', prev_wednesday($_), for qw( 20150804 20150805 20150806
20150101 20000301 20010301 );
答案 1 :(得分:2)
总有蛮力的方法。
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use POSIX 'strftime';
my $ONE_DAY = 24 * 60 * 60;
# Get now
my $time = time;
# Subtract days until you get to a Wednesday
do {
$time -= $ONE_DAY;
} until (localtime($time))[6] == 3;
# Format
say strftime '%Y%m%d', localtime $time;
但是如果您在Perl环境中工作,无法从CPAN安装模块,那么删除该限制总是值得的。现代Perl编程通常是将正确的CPAN模块系列连接在一起的情况。如果你无法访问CPAN,那么你的生活就会比你需要的更加努力。
如果你真的无法解除限制,那么找另一份工作。与那些施加这种毫无意义的限制的人打交道并不值得。
更新:刚刚注意到您还使用了Perl的史前版本。您需要删除use 5.010
并将say
替换为print
。并刷新你的简历: - /
更新2: choroba的解决方案更好。它以正确的格式处理任何日期。我只是处理当前日期。关于修复工作环境的建议仍然存在。
答案 2 :(得分:2)
使用Time::Piece
:
use feature qw(say);
use strict;
use warnings;
use Time::Piece;
use Time::Seconds;
my $str = '20150804';
my $fmt = '%Y%m%d';
my $t = Time::Piece->strptime($str, $fmt);
do {
$t = $t - ONE_DAY;
} until ( $t->day eq 'Wed');
say $t->strftime($fmt);
答案 3 :(得分:2)
这是一个更优雅的解决方案,不会做暴力。
use strict;
use warnings;
use Time::Local 'timelocal';
use POSIX 'strftime';
my $dt = "20150804";
say getPrevWednesday($dt);
# note you do not want () here,
# see http://perldoc.perl.org/perlsub.html#Prototypes
sub getPrevWednesday {
my $givenDt = shift;
# parse the string into a unix timestamp
my ( $year, $month, $day ) = $givenDt =~ /(....)(..)(..)/;
my $timestamp = timelocal( 0, 0, 12, $day, $month - 1, $year );
# get the day of week, ignore the rest
my ( undef, undef, undef, undef, undef, undef, $wday ) =
localtime $timestamp;
# because we start the week with Sunday on day 0
# and to get to the previous Wednesday from Sunday it's
# 4 days (Wednesday is 3) we can add 4 to the
# number of this day, divide by 7, take the leftover (modulo)
# and then subtract that many days
# (86_400 is one day in seconds)
# v- -6 ------
# 6 % 7 = 6
# +4 -----v
# v
# 0 1 2 3 4 5 6 0 1 2 3 4 5 6
# S M T W T F S S M T W T F S
my $prev_wed = $timestamp - ( ( $wday + 4 ) % 7 * 86_400 );
# go one week back if we got the same day
$prev_wed -= ( 7 * 86_400 ) if $prev_wed == $timestamp;
# debug output
warn "in: " . localtime($timestamp) . "\n";
warn "out: " . localtime($prev_wed) . "\n\n";
# put it back into your format
return strftime('%Y%m%d', localtime $timestamp);
}
输出:
# STDOUT
20150804
# STDERR
in: Tue Aug 4 12:00:00 2015
out: Wed Jul 29 12:00:00 2015