5 ответов:
Это очень похоже на другой вопрос, который вы задали пару дней назад. Поэтому неудивительно, что решение также очень похоже.
Time:: Piece и Time:: Seconds были частью стандартного дистрибутива Perl начиная с версии 5.10.0. Вы должны использовать их.
#!/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;
Perl хранит даты и время во внутреннем формате, которым можно легко манипулировать. У вас есть дата в формате YYYYMMDD. Итак, что вам нужно сделать:
- преобразуйте вашу дату (которая находится в формате YYYYMMDD) в формат хранения даты/времени Perl.
- используйте Perl для управления этой датой и временем.
- Когда вы хотите вывести результаты, вы должны преобразовать их обратно в нужный формат.
Преобразование даты (которая находится в формате YYYYMMDD) в формат хранения даты и времени Perl.
Лучший модуль для этого - Time::Piece , который поставляется с Perl. Это довольно просто:
my $date = Time::Piece->strptime($str1, '%Y%m%d');
$dateтеперь будет ваша дата и время, но сохраненные в формате Perl можно понять и манипулировать.%Y%m%d- это описание вашего формата, поэтому Perl знает, где найти год, месяц и день месяца. Вы можете посмотреть на strftime, чтобы увидеть различные параметры формата. В вашем случае:
%Y- представляет год с веком, например2012.%m- представляет месяц в виде двухзначного числа, например03или12.%d- представляет дату месяца в виде двухзначного числа от01до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('');Это очень мило. простой.
Дейв Кросс дал вам превосходный ответ. Обычно я просто голосовал за него, и на этом все заканчивалось. Однако он также упомянул, что вы задавали подобный вопрос несколько дней назад. Для меня это означает, что вы могли использовать предыдущий ответ Дэйва Кросса, но вы его не поняли. Это нехорошо.
Посмотрите документацию Time::Piece и Time::Seconds. Взгляните на strfdate и поиграйте с этим. Выучите его и понять это. Если у вас есть какие-либо вопросы по этому поводу, задайте их на Stackoverflow. Люди на Stackoverflow более счастливы, отвечая на вопросы типа "как это работает?"а не "ты можешь сделать это для меня?". Они потратят время и усилия, чтобы объяснить первое, в то время как большинство либо проигнорирует последнее, либо даст вам краткий ответ.
Это сделает вас лучшим программистом, что означает, что вы более ценны в своей компании, и это приведет к более высокой оплате труда. Это стоит вашего времени и усилие. Попытайтесь понять это. Поиграйте с ним.
Добавление
Это довольно старая версия Perl, но она распространена на Солярисе. В данном случае мы сделаем это очень старомодным способом. Есть две функции Perl, называемыеlocaltime иgmtime . Эти возьмите число секунд с 1 января 1970 года и преобразуйте его в массив значений, каждое из которых представляет определенную часть времени (месяц, год, День, часы, минуты и т. д.).). Что вам нужно, так это обратные функции - что-то, что может взять массив значений и преобразовать его в число секунд с 1970 года. Начиная с Perl 3.0, такой модуль был включен в каждую версию Perl. В Perl 5.x, tt называется Time:: Local . Это дает вам два функции называютсяИспользовал старую версию perl 5.8 и думал об использовании существующих модулей в системе. Также не уверен в том, как работает time:: piece
timelocalиtimegm. Это те обратные функции, которые нам нужны. Во-первых, нам нужно разделить вашу строку на отдельные год, месяц и день, поместить их в массив дляtimegmилиtimelocal, чтобы превратить в число секунд с 1 января 1970 года. Далее мы вычтем количество секунд в сутках. Это и есть 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;
Я советую вам использовать модуль
DateTimeи один ext для формата. Также вы можете увидеть модулиDate::CalcилиDate::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;
Подойдет ли это?
use Date::Parse; use POSIX; my $s1 = "20120704"; my $t = str2time($s1) - 86400; my $s2 = strftime "%Y%m%d", localtime $t; print "$s2\n";Следите за
localtimeпротивgmtime, и прыжковые секунды, если вы заботитесь о них.
Это просто
strptime/strftimeтуда и обратно. Посколькуstrftimeнормализует входные данные, достаточно просто вычесть 1 из поля mday.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;
Comments