2012-08-29 9 views
5

Zastanawiam się, czy istnieje wbudowana funkcja Perla, która dostosowuje datę, jeśli bierzesz z niej miesiąc. Na przykład. jeśli data jest 31, to dostosuje się do końca poprzedniego miesiąca, jeśli nie ma 31 dni.Jak wrócić miesiąc w Perlu biorąc pod uwagę różne dni w miesiącu?

Po prostu zmienię go na 30. Łatwo, gdyby nie były to miesiące z 31 dniami obok siebie (grudzień/styczeń, lipiec/sierpień) i luty. Chcę tylko zapisać datę w określonym czasie poza bieżącą datą, np.

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); 

$current_date = join("-", (1900+$year), ($mon+1), $mday); 
$one_month_ago = join("-", (1900+$year), ($mon), $mday); 
$one_year_ago = join("-", (1899+$year), ($mon+1), $mday); 

mogę poradzić sobie z instancji lutego, ponieważ odnosi się tylko do lata, ale jeśli ta została podjęta w dniu 31 grudnia 2012 roku, a następnie zabierając miesiąc oznaczałby 31. lis 2012, co oczywiście nie istnieje. Myślałem, że chciałbym zapytać, czy istnieje funkcja przed komplikowania rzeczy dla siebie ... dzięki :)

+2

[DateTime] (https://metacpan.org/module/DateTime) Może szukasz tego modułu? (ma datę "matematyka") – gaussblurinc

+0

Obie odpowiedzi poniżej dobre! Date Time wygląda na naprawdę użyteczną opcję, ale ponieważ chcę ją wykorzystać dla niewielkiej części mojego kodu, myślę, że mogę po prostu zanurzyć się i zrobić dla niej kilka klauzul. Długo się kręci, ale to pomoże mi się uczyć ... to jest mój pierwszy dzień korzystania z Perla: P Dziękuję za pomoc! – dgBP

Odpowiedz

8

Inni sugerowali DateTime, ale jest to dość duży, non-core i może być powolne.

znacznie prostsze rozwiązanie polega na wykorzystaniu Builtin localtime i POSIX::mktime funkcje:

use POSIX qw(mktime); 

my @t = localtime $epoch; 
$t[4] -= 2; # $t[4] is tm_mon 
my $two_months_ago = mktime @t; 

Funkcja mktime() szczegółowo uchwyty wartości denormalised; poradzi sobie z tym, że Janurary minus 2 miesiące to listopad poprzedniego roku, itd. Zachowa on tę samą sekundę/minutę/godzinę dnia i ten sam dzień miesiąca.

+0

Wygląda to bardzo dobrze, ale nie mogę go wydrukować na podstawie danych $ two_months_ago, ponieważ jest niezainicjowany (zainicjowałem go bez zmian). – dgBP

+0

Działa dla mnie: http://pastie.org/4610603 – LeoNerd

+0

z tym innym kodem, który rzeczywiście robi! Muszę powiedzieć, że jest to lepsza wersja, której szukałem :) kudos – dgBP

10

DateTime nie jest wbudowany w module, ale po zainstalowaniu go, czyni to matematyka trywialny:

#!/usr/bin/perl 
use strict; 
use warnings; 

use feature qw(say); 
use DateTime; 

my $dt = DateTime->now; 
say $dt->ymd; 

$dt->truncate(to => month); 

say $dt->ymd; 

$dt->add(days => -1); 
say $dt->ymd; 

foreach (1 .. 12) { 
    $dt->add(months => -1); 
    say $dt->ymd; 
} 

Kiedy uruchomić to dzisiaj (29 sierpnia 2012) pojawia się następujący komunikat:

[~] $ perl dt.pl 
2012-08-29 
2012-08-01 
2012-07-31 
2012-06-30 
2012-05-31 
2012-04-30 
2012-03-31 
2012-02-29 
2012-01-31 
2011-12-31 
2011-11-30 
2011-10-31 
2011-09-30 
2011-08-31 
2011-07-31 
+0

Szczerze mówiąc, gdybym mógł podać dwie najlepsze odpowiedzi, zrobiłbym, ale masz trochę więcej informacji :) dzięki! Nigdy nie widziałem funkcji wypowiedzenia - warto o tym wiedzieć! – dgBP

+0

Ta funkcja zależy od wersji Perla. Powinno być> = 5,10 –

7

Jeśli masz szansę, aby zainstalować moduł DateTime. Daje to wiele korzyści, gdy masz do czynienia z datami.

use strict; 
use DateTime; 

my $epoch = ...; 
my $dt = DateTime->from_epoch(epoch => $epoch); 
$dt->subract(months => 1); 

printf "%s", $dt->datetime(); 
+0

dobrze, dzięki! :) – dgBP

Powiązane problemy