web-dev-qa-db-ja.com

PerlでYYYY-mm-dd HH:MM:SSにすばやく到達する

Perlスクリプトを記述するとき、_YYYY-mm-dd HH:MM:SS_(たとえば_2009-11-29 14:28:29_)としてフォーマットされた文字列として表される現在の時刻を取得する必要があることがよくあります。

これを行う際に、私はこの非常に面倒なパスを取っていることに気付きます

  • _man perlfunc_
  • _/localtime_ localtimeを検索する-5回繰り返して(_/_ + _\n_)、マンページの関連セクションに到達します
  • 文字列_($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);_をマンページからスクリプトにコピーします。
  • my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year, $mon, $mday, $hour, $min, $sec);で試してください
  • 覚えておきたいこと1:現在の年を取得するには、$ yearに1900を追加する必要があります。
  • my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon, $mday, $hour, $min, $sec);で試してください
  • 覚えておいてください#2:今月を取得するには、$ monに1を追加する必要があります。
  • my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);で試してください
  • 大丈夫だ。できた!

上記のプロセスは機能しますが、最適とはほど遠いものです。よりスマートな方法があると確信しているので、私の質問は単純です:

Perlで現在の日付/時刻の_YYYY-mm-dd HH:MM:SS_を取得する最も簡単な方法は何ですか?

「簡単」には、「書きやすい」と「覚えやすい」の両方が含まれます。

61
knorv

標準の strftime モジュールでPOSIXを使用します。 Perlバインディングの strftime の引数は、 localtime および gmtime 。比較する

strftime(fmt, sec, min, hour, mday, mon, year, wday = -1, yday = -1, isdst = -1)

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

コマンドラインの使用例は

$ Perl -MPOSIX -le 'print strftime "%F %T", localtime $^T'

またはソースファイルから

use POSIX;

print strftime "%F %T", localtime time;

一部のシステムは%Fおよび%Tの短縮形をサポートしていないため、明示的に指定する必要があります

print strftime "%Y-%m-%d %H:%M:%S", localtime time;

または

print strftime "%Y-%m-%d %H:%M:%S", gmtime time;

time は、呼び出されたときに現在の時刻を返しますが、 $^T はプログラムが開始された時刻に固定されていることに注意してください。 gmtime の場合、戻り値はGMTの現在の時刻です。 localtime を使用して、ローカルタイムゾーンの時間を取得します。

71
Greg Bacon

DateTimeモジュールを使用して、汚い仕事をしていないのは何ですか? and覚えやすい!

use strict;
use warnings;
use DateTime;

my $dt   = DateTime->now;   # Stores current date and time as datetime object
my $date = $dt->ymd;   # Retrieves date as a string in 'yyyy-mm-dd' format
my $time = $dt->hms;   # Retrieves time as a string in 'hh:mm:ss' format

my $wanted = "$date $time";   # creates 'yyyy-mm-dd hh:mm:ss' string
print $wanted;

何が起こっているのかがわかれば、tempを取り除き、数行のコードを保存できます。

use strict;
use warnings;
use DateTime;

my $dt = DateTime->now;
print join ' ', $dt->ymd, $dt->hms;
32
Zaid

これを試して:

use POSIX qw/strftime/;
print strftime('%Y-%m-%d',localtime);

strftimeメソッドは、私にとって効果的な仕事をします。非常にシンプルで効率的。


30
Vish

Time :: Piece (Perl 5.10以降のコア内)にはstrftime関数もあり、デフォルトでlocaltimeとgmtimeをオーバーロードしてTime :: Pieceオブジェクトを返します:

use Time::Piece;
print localtime->strftime('%Y-%m-%d');

または、オーバーライドされた現地時間なし:

use Time::Piece (); 
print Time::Piece::localtime->strftime('%F %T');
13
MkV

次のブロックをそれぞれ1.000.000回呼び出す小さなテスト(VMのFreeBSDでのPerl v5.20.1)を行いました。

A

my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year+1900, $mon+1, $mday, $hour, $min, $sec);

B

my $now = strftime('%Y%m%d%H%M%S',localtime);

C

my $now = Time::Piece::localtime->strftime('%Y%m%d%H%M%S');

次の結果があります。

A:2秒

B:11秒

C:19秒

もちろん、これは完全なテストやベンチマークではありませんが、少なくとも私にとっては再現可能です。したがって、より複雑ですが、datetimestampの生成が非常に頻繁に必要な場合は、最初の方法をお勧めします。

呼び出し(例:FreeBSD 10.1の下)

my $now = `date "+%Y%m%d%H%M%S" | tr -d "\n"`;

oSに依存せず、かなり時間がかかるため、あまり良いアイデアではないかもしれません。

よろしく、ホルガー

5
Holger

正確な形式ではなく、人間が読み取れる時間文字列が必要な場合:

$t = localtime;
print "$t\n";

プリント

Mon Apr 27 10:16:19 2015

またはあなたのロケール用に設定されているものは何でも。

3
robm

Time::Piece::datetime()Tを削除できます。

use Time::Piece;
print localtime->datetime(T => q{ });
3
ernix

短くて甘い、追加のモジュールは不要:

my $toDate = `date +%m/%d/%Y" "%l:%M:%S" "%p`;

たとえば、出力は2017年4月25日午前9時30分33秒です。

1
Off The Gold

多くの場合、必要な「現在時刻」はむしろ$ ^ Tです。これは、スクリプトが実行を開始した時刻であり、UNIXエポック以降の秒単位(60秒と仮定)で表されます。

これにより、スクリプトの初期部分が、クエリ条件やその他の派生値など、スクリプトの後半部分とは異なる日付(または夏時間ステータス)を使用することを防ぎます。

'現在時刻'のそのバリアントでは、定数を使用して、コンパイル時に凍結されたことを文書化することもできます。

use constant YMD_HMS_AT_START => POSIX::strftime( "%F %T", localtime $^T );

別の高解像度の起動時間:

0+ [ Time::HiRes::stat("/proc/$$") ]->[10]
1
druid62