2012-08-29 32 views
5

Tôi đã tự hỏi nếu có một chức năng Perl trong xây dựng mà điều chỉnh ngày nếu bạn mất một tháng từ nó. Ví dụ. nếu ngày là ngày 31, nó sẽ điều chỉnh để kết thúc tháng trước nếu nó không có 31 ngày.Làm thế nào để quay trở lại tháng trong Perl lấy tài khoản của các ngày khác nhau trong tháng?

Tôi chỉ thay đổi nó thành 30 dễ dàng nếu không phải trong những tháng có 31 ngày cạnh nhau (tháng 12/tháng 1, tháng 7/tháng 8) và tháng 2. Tôi chỉ muốn lưu trữ ngày một khoảng thời gian nhất định từ ngày hiện tại, ví dụ:

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); 

tôi có thể đối phó với các trường hợp tháng hai như nó chỉ áp dụng cho năm nay, nhưng nếu điều này được chụp vào ngày 31 Tháng 12 năm 2012 sau đó lấy đi một tháng sẽ có nghĩa là 31 tháng 11 năm 2012, trong đó tất nhiên không tồn tại. Tôi nghĩ rằng tôi sẽ hỏi nếu có một chức năng trước khi làm phức tạp những điều cho bản thân mình ... cảm ơn :)

+2

[Ngày giờ] (https://metacpan.org/module/DateTime) có thể bạn tìm kiếm mô-đun này? (nó có ngày 'toán học) – gaussblurinc

+0

Cả hai câu trả lời dưới đây tốt! Ngày giờ trông giống như một lựa chọn thực sự hữu ích, nhưng khi tôi muốn sử dụng nó cho một phần nhỏ của mã của tôi, tôi nghĩ rằng tôi có thể chỉ cần lao vào và thực hiện một loạt các mệnh đề cho nó. Dài gió, nhưng nó sẽ giúp tôi tìm hiểu ... đây là ngày đầu tiên của tôi bằng cách sử dụng Perl: P Cảm ơn sự giúp đỡ của bạn! – dgBP

Trả lời

8

Những người khác đã đề xuất DateTime, nhưng nó khá lớn, không cốt lõi và có thể chậm.

Một giải pháp đơn giản hơn nhiều là sử dụng được xây dựng trong localtimePOSIX::mktime chức năng:

use POSIX qw(mktime); 

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

Chức năng mktime() đặc biệt xử lý các giá trị denormalised; nó sẽ đối phó với thực tế là Janurary trừ đi 2 tháng là tháng 11 của năm trước, vv .. Nó sẽ giữ nguyên giây/phút/giờ trong ngày và cùng ngày trong tháng.

+0

Điều này trông rất tốt, nhưng tôi không thể làm cho nó để in ra con số $ hai_months_ago vì nó nói nó là uninitialized (tôi sau đó khởi tạo nó không có thay đổi). – dgBP

+0

Hoạt động cho tôi: http://pastie.org/4610603 – LeoNerd

+0

với mã khác đó thực sự! Tôi phải nói rằng đó là một phiên bản tốt hơn mà tôi đang tìm kiếm :) kudo – dgBP

10

DateTime không phải là một mô-đun tích hợp, nhưng một khi bạn đã cài đặt nó, nó làm cho toán này tầm thường:

#!/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; 
} 

Khi tôi chạy hôm nay (ngày 29 tháng 8 2012) tôi nhận được kết quả như sau:

[~] $ 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

Thành thật mà nói, nếu tôi có thể đưa ra hai câu trả lời hay nhất tôi sẽ làm, nhưng bạn có thêm một chút thông tin :) cảm ơn! Tôi chưa bao giờ thấy tính năng nói - đó là điều hữu ích để biết! – dgBP

+0

Tính năng này phụ thuộc vào phiên bản của Perl. Nó phải> = 5.10 –

7

Nếu bạn có một cơ hội để cài đặt mô-đun DateTime. Nó cung cấp cho bạn rất nhiều đặc quyền, khi bạn đã đối phó với ngày tháng.

use strict; 
use DateTime; 

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

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

tốt, cảm ơn! :) – dgBP

Các vấn đề liên quan