在Perl中,如何解析日期字符串并从它代表的日期中减去天数?

Ara*_*rav 2 perl datetime

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

Dav*_*oss 11

这与您几天前提出的另一个问题非常相似.因此,毫不奇怪,解决方案也非常相似.

Time :: Piece和Time ::自版本5.10.0以来,Seconds已经成为标准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;
Run Code Online (Sandbox Code Playgroud)

  • PErl 5.8.0已有十年历史.是时候更新了! (2认同)

Dav*_* W. 9

Perl以可以轻松操作的内部格式存储日期和时间.你所拥有的是YYYYMMDD格式的日期.那么,你需要做的是:

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

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

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

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

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

  • %Y- 代表与世纪的一年,如2012.
  • %m- 将月份表示为两位数字,例如0312.
  • %d-从表示月份的两位数字的日期0131是否有在一个月多天.

下一步:操纵您的日期.

您可以使用另一个名为Time :: Seconds的模块来处理这个问题.

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

 my $date = $date - ONE_DAY;
Run Code Online (Sandbox Code Playgroud)

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

再次,Time::Piece有一个漂亮,简单的方法为您做到这一点:

$date->ymd("");
Run Code Online (Sandbox Code Playgroud)

这将转换$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('');
Run Code Online (Sandbox Code Playgroud)

这很简单.


Dave Cross给了你一个很好的答案.我通常只是投票给他,并留下它.不过,他也提到你几天前问了一个类似的问题.对我而言,这意味着您可能已经使用过Dave Cross之前的答案,但您并不理解它.这不好.

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

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

试着理解它.玩弄它.


附录

使用较旧的perl版本5.8并考虑使用系统中的现有模块.也不确定time :: piece的工作原理

这是Perl的旧版本,但它在Solaris上很常见.

在这种情况下,我们将以非常古老的方式进行.

有两个名为localtimegmtime的 Perl函数.这些采用自1970年1月1日以来的秒数并将其转换为值数组,每个值表示时间的特定部分(月,年,日,小时,分钟等).

你需要的是反函数 - 可以采用一系列值并将其转换为自1970年以来的秒数.自Perl 3.0以来,Perl的每个版本都包含了这样的模块.在Perl 5.x中,tt称为Time :: Local.它为您提供了两个名为timelocal和的函数timegm.这些是我们需要的反函数.

首先,我们需要将字符串分割成单独的年,月,日,并将它放入了一个任意阵列timegmtimelocal自1970年1月1日,转成秒数.

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

最后,我们将该新日期转换为可用于以YYYYMMDD顺序显示日期的数组.

两个重要的警告!

  • 该函数假定月份为0到11而不是1到12.这允许您创建一个数组以将月号转换为名称.这意味着我们必须从我们提供之前的月份中减去1,gmtime并在从中取回时添加一个timegm.
  • 这一年是自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;
Run Code Online (Sandbox Code Playgroud)


Pav*_*sov 8

我建议你使用模块DateTime和一个ext格式.你也可以看模块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;
Run Code Online (Sandbox Code Playgroud)