アプリ版:「スタンプのみでお礼する」機能のリリースについて

Perlで日付を取得する

perlで1週間分の日付を取得し、セレクトボックスに格納したいと思っています。

なるべくいま使っているサブルーチンを使いたいです。

# 現在日時を文字列化する
sub get_date_string {
# local(@week) = ("日", "月", "火", "水", "木", "金", "土");
local(@week) = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
local($sec, $min, $hour, $day, $mon, $year, $weekday) = localtime(time);
$year += 1900;
$mon++;
# 文字列化する
if ($hour < 10) {
$hour = "0$hour";
}
if ($min < 10) {
$min = "0$min";
}
if ($sec < 10) {
$sec = "0$sec";
}
$weekstr = $week[$weekday];
return "$year-$mon-$day ($weekstr) $hour:$min";
# return "$year年$mon月$day日 ($weekstr) $hour時$min分$sec秒";
}


これを別のルーチンで、

$today = substr(&get_date_string,0,10);
$kinou = $today - 1;
$ototoi = $today - 2;

として、今日の日付だけでなく、昨日、おととい、その前の日を取得したいと試みましたが、今日は取得できても、$kinouや$ototoiは、すごい数字になってしまいます。

変わりに -24*3600と引いてみましたがダメでした。

文字列に変更されていないから引けないのでしょうか?

かんたんに処理できそうでできないので、詳しいやり方を教えてください。

A 回答 (5件)

書式付の日付は、strftimeを使うと便利です。



既存のget_date_string関数を変えたくないとのことなので、過去の日付を得る新たな関数get_past_dateというのを作ってみました。

でも、無駄が多いので、極力エポック秒を操作することを考えたほうがいいと思います。参考程度に見てください。

use POSIX 'strftime';
use Date::Calc 'Add_Delta_Days';

sub get_date_string {
return strftime("%Y-%m-%d (%a) %H:%M", localtime);
}

sub get_past_date {
my ($today, $offset_days) = @_;

my ($past_year, $past_month, $past_day) = Add_Delta_Days(split(/-/, $today), $offset_days);
return sprintf("%4d-%02d-%02d", $past_year, $past_month, $past_day);
}

my $today = substr(&get_date_string,0,10);
my $kinou = get_past_date($today, -1);
my $ototoi = get_past_date($today, -2);

print "today=$today\n";
print "kinou=$kinou\n";
print "ototoi=$ototoi\n";
    • good
    • 0

sub get_date_string {


my $now=shift||time; # 追加
# local(@week) = ("日", "月", "火", "水", "木", "金", "土");
local(@week) = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
local($sec, $min, $hour, $day, $mon, $year, $weekday) = localtime($now); # timeのところを変更
# 後略
}

使い方

$today = substr(&get_date_string(time),0,10); # 今日の日付
$kinou = substr(&get_date_string(time-24*3600),0,10); # 昨日の日付
$ototoi = substr(&get_date_string(time-2*24*3600),0,10); # 一昨日の日付

未検証です。

todayはtime-(0*24*3600)
kinouはtime-(1*24*3600)
ototoiはtime-(2*24*3600)
のように順番になってるので、ループにするとかのアレンジも出来ると思います。
    • good
    • 0

localtime の引数に使っている関数「time」は、「エポック秒」と呼ばれる「1971年1月1日0時0分を基準とした秒」単位で現在の時刻を返す関数です。


そのエポック秒から年月日時分秒に変換するのがlocaltime関数。

ですので、現在の時刻から24*60*60とか2*24*60*60を引いた数値をlocaltimeの引数にすれば、昨日や一昨日の日時を得ることができます。
あとは、$hour や $min の処理が泥臭いので、sprintfでもっとシンプルに書いてみました。

回答2のようにget_date_stringの引数を現在時からのずらす日数にした方が呼び出しは簡単になりますが、
そうすると、get_date_stringの呼び出しのたびに毎回現在時刻を取得するので、処理に時間がかかったときに、表示時刻がずれていく、という問題があります。
できれば、現在時刻の取得は一回だけにしておいたほうがいいと思います。

---ここから---
use strict;
use warnings;

# 指定日時を文字列化する
sub get_date_string {
my($time) = $_[0] || time;
my(@week) = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
#my(@week) = ("日", "月", "火", "水", "木", "金", "土");
my($sec, $min, $hour, $day, $mon, $year, $weekday) = localtime($time);
return sprintf("%4d-%02d-%02d (%s) %02d:%02d", $year+1900, $mon+1, $day, $week[$weekday], $hour, $min);
#return sprintf("%4d年%02d月%02d日 (%s) %02d時%02d分%02d秒", $year+1900, $mon+1, $day, $week[$weekday], $hour, $min, $sec);
}

my $time = time; #現在時刻を取得
my $today = get_date_string($time); #現在の日時
my $kinou = get_date_string($time - 1 * 24 * 60 * 60); #1*24*60*60秒=1日前の日時
my $ototoi = get_date_string($time - 2 * 24 * 60 * 60); #2*24*60*60秒=2日前の日時

print "today=$today\n";
print "kinou=$kinou\n";
print "ototoi=$ototoi\n";
---ここまで---
    • good
    • 0

こんな感じでいかがでしょうか?


2010-9-20 (Mon) 17:24
2010-9-19 (Sun) 17:24
2010-9-18 (Sat) 17:24
と表示されてます。


use strict;
use warnings;

my $today = &get_date_string(0);
my $kinou = get_date_string(-1);
my $ototoi = get_date_string(-2);
print $today, "\n";
print $kinou, "\n";
print $ototoi, "\n";

sub get_date_string {
my ($change_day) = @_; #日付修正

# local(@week) = ("日", "月", "火", "水", "木", "金", "土");
my (@week) =
( "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ); #myにしました
my ( $sec, $min, $hour, $day, $mon, $year, $weekday ) =
localtime( time + $change_day * 24 * 3600 ); #日付修正
$year += 1900; #myにしました
$mon++;

# 文字列化する
if ( $hour < 10 ) {
$hour = "0$hour";
}
if ( $min < 10 ) {
$min = "0$min";
}
if ( $sec < 10 ) {
$sec = "0$sec";
}
my $weekstr = $week[$weekday]; #my にしました
return "$year-$mon-$day ($weekstr) $hour:$min";

# return "$year年$mon月$day日 ($weekstr) $hour時$min分$sec秒";
}
    • good
    • 0

はっきり言って「このルーチンを使って何とかしよう」というのは間違いだ. time の返り値に対して操作することを考えるべき.


しかし, なんというか涙ぐましい (けど無駄な) 努力だなぁ.... sprintf を覚えよう.
あ, あとこの文脈で local は古臭いので, できれば my を使った方がいいと思うよ.
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!