2

我在字符串中有一个日期,如$str1="20120704". 我想从该日期减去 1 天,并将日期的值作为字符串存储在$str2. 我该怎么做?

4

5 回答 5

11

这与您几天前提出的另一个问题非常相似。因此,不出所料,解决方案也非常相似。

Time::Piece 和 Time::Seconds 自 5.10.0 版以来一直是标准 Perl 发行版的一部分。你应该使用它们。

#!/usr/bin/perl

use strict;
use warnings;
use 5.010;

use Time::Piece;
use Time::Seconds;

my $format = '%Y%m%d';
my $str1 = '20120704';

my $dt1 = Time::Piece->strptime($str1, $format);
my $dt2 = $dt1 - ONE_DAY;
my $str2 = $dt2->strftime($format);
say $str2;
于 2012-07-08T15:12:22.453 回答
9

Perl 以易于操作的内部格式存储日期和时间。您所拥有的是 YYYYMMDD 格式的日期。所以,你需要做的是:

  1. 将您的日期(格式为 YYYYMMDD)转换为 Perl 的日期/时间存储格式。
  2. 使用 Perl 来操作这个日期和时间。
  3. 当您想要输出结果时,您必须将其转换回您想要的格式。

将您的日期(格式为 YYYYMMDD)转换为 Perl 的日期/时间存储格式。

执行此操作的最佳模块是Perl 附带的Time::Piece 。这很简单:

my $date = Time::Piece->strptime($str1, '%Y%m%d');

$date现在将是您的日期和时间,但以 Perl 可以理解和操作的格式存储。这%Y%m%d是对格式的描述,因此 Perl 知道在哪里可以找到年月日。您可以查看strftime以查看各种格式参数。在你的情况下:

  • %Y- 表示带有世纪的年份,如2012.
  • %m- 将月份表示为两位数,例如0312
  • %d-如果一个月中有那么多天,则将月份的日期表示为从01to的两位数。31

下一步:操纵你的日期。

您可以使用另一个名为Time::Seconds的模块来为您解决这个问题。

Time::Seconds定义了一堆常量,比如ONE_DAY让事情变得更容易:

 my $date = $date - ONE_DAY;

最后:将日期转换回您想要的格式。

同样,Time::Piece有一个漂亮、简单的方法可以为您做到这一点:

$date->ymd("");

这将转换$date为年-月-日格式的字符串。默认情况下,这将-在每个部分之间放置一个。但是,您可以将要用作分隔符的字符传递给它。在这种情况下,什么都没有。

全部一起:

use Time::Piece   # For manipulating and storing the date
use Time::Seconds # For the nice constants such as ONE_DAY and ONE_WEEK

my $date = Time::Piece->strptime($str1, '%Y%m%d');
my $date = $date - ONE_DAY;
my $str2 = $date->ymd('');

这很简单。


戴夫克罗斯给了你一个很好的答案。我通常只是投他一票,然后就这样。不过,他也提到你前几天问了一个类似的问题。对我来说,这意味着您可能使用过 Dave Cross 之前的答案,但您并不理解它。这不好。

查看Time::PieceTime::Seconds的文档。看看strfdate并玩弄它。学习它并理解它。如果您对这些有任何疑问,请在 Stackoverflow 上提问。Stackoverflow 上的人们更乐于回答诸如“这是如何工作的?”之类的问题。而不是“你能为我做这件事吗?”。他们会花时间和精力来解释第一个,而大多数人要么忽略后者,要么给你一个粗略的答案。

这将使您成为更好的程序员,这意味着您对公司更有价值,并转化为更高的薪水。值得您花时间和精力。

试着理解它。玩弄它。


附录

正在使用较旧的 perl 版本 5.8,并考虑使用系统中的现有模块。也不确定 time::piece 是如何工作的

这是一个相当老的 Perl 版本,但在 Solaris 上很常见。

在这种情况下,我们将采用非常古老的方式。

有两个 Perl 函数称为localtimegmtime。这些取自 1970 年 1 月 1 日以来的秒数,并将其转换为一个值数组,每个值代表时间的特定部分(月、年、日、小时、分钟等)。

您需要的是反函数——它可以获取一组值并将其转换为自 1970 年以来的秒数。从 Perl 3.0 开始,每个版本的 Perl 中都包含了这样一个模块。在 Perl 5.x 中,tt 称为Time::Local。它为您提供了两个称为timelocal和的函数timegm。这些是我们需要的反函数。

首先,我们需要将您的字符串拆分为单独的年、月和日,将其放入一个数组中,timegm或者timelocal转换为自 1970 年 1 月 1 日以来的秒数。

接下来,我们将减去一天中的秒数。这是 60 * 60 * 24 或 86,400。

最后,我们将该新日期转换为一个数组,您可以使用该数组以 YYYYMMDD 顺序显示日期。

两个重要的警告!

  • 该函数假定月份是从 0 到 11 而不是 1 到 12。这允许您创建一个数组以将月份编号转换为名称。这意味着我们必须在给它之前的月份减去 1,gmtime并在取回它时加上 1 timegm
  • 年份是自 1900 年以来的年数。这意味着我们必须在将 1900 给 给 之前减去 1900,gmtime从 取回时加上 1900 timegm

而且,现在的程序:

#! /usr/bin/env perl

use strict;
use warnings;

use Time::Local;

my $date = 20120615;    #2012-June-15

$date =~ /(....)(..)(..)/;  #Parse the date

my $year = $1;
my $month = $2;
my $day = $3;

$month -= 1;    #Month is 0 to 11 and not 1 to 12
$year -= 1900;  #Year is number of years since 1900

my $seconds = 0;
my $minutes = 0;
my $hours = 0;

my $perl_date = timegm($seconds, $minutes, $hours, $day, $month, $year);

my $perl_date2 = $perl_date - (60 * 60 *24);

my ($seconds2, $minutes2, $hours2, $day2, $month2, $year2)  = gmtime($perl_date2);

$month2 += 1;   #Month is returned as 0 - 11. Make 1 - 12
$year2 += 1900; #Year is given as years since 1900. Add 1900 back to it. 

printf qq(The date is %04d-%02d-%02d \n), $year2, $month2, $day2;
于 2012-07-08T17:41:52.763 回答
8

我建议你使用模块DateTime和一个分机作为格式。您还可以查看模块Date::CalcDate::Parse+POSIX函数 strftime。

use strict;
use DateTime;
use DateTime::Format::Strptime;

my $date_str = '20120704';
my $date_obj = DateTime::Format::Strptime->parse_datetime($date_str);

my $date_res = $date_obj->subtract(days => 1)->ymd;
于 2012-07-08T12:01:55.870 回答
1

这是一个简单的strptime/strftime往返。由于strftime规范化输入,只需从 mday 字段中减去 1。

use POSIX 'strftime';
use POSIX::strptime 'strptime';

my $fmt = "%Y%m%d";
my @t = strptime "20120704", $fmt;
$t[3] -= 1;  # 1 day
my $str2 = strftime $fmt, @t;
于 2012-07-08T14:11:16.687 回答
1

这会吗?

use Date::Parse;
use POSIX;

my $s1 = "20120704";
my $t = str2time($s1) - 86400;
my $s2 = strftime "%Y%m%d", localtime $t;

print "$s2\n";

如果您关心这些,请注意 vs 和闰秒localtimegmtime

于 2012-07-08T12:01:59.773 回答