web-dev-qa-db-ja.com

Perlで日付/時刻をエポック時間(1970年以降のUNIX時間/秒)に変換するにはどうすればよいですか?

(年、月、日、時、分、秒)の配列として日付/時刻を指定すると、それをエポック時刻、つまり1970-01-01 00:00:00 GMT以降の秒数にどのように変換しますか?

おまけの質問:日付/時刻を文字列として指定した場合、どのように最初に(y、m、d、h、m、s)配列に解析しますか?

42
dreeves

これは、Unix時間を取得する最も簡単な方法です。

use Time::Local;
timelocal($second,$minute,$hour,$day,$month-1,$year);

引数の逆順と、1月が月0であることに注意してください。その他のオプションについては、CPANの DateTime モジュールを参照してください。

解析については、CPANの Date :: Parse モジュールを参照してください。日付の解析に本当に興味がある場合は、 Date :: Manip が役立つかもしれませんが、多くの荷物を運んでいるので、それ自体のドキュメントでは警告されます(一般的なビジネスのようなことを知っています)休日など)やその他のソリューションははるかに高速です。

解析する日付/時刻の形式について何か知っている場合は、単純な正規表現で十分かもしれませんが、適切なCPANモジュールを使用する方が良いでしょう。たとえば、日付が常にYMDHMSの順序になることがわかっている場合は、CPANモジュール DateTime :: Format :: ISO8601 を使用します。


私自身の参考のために、以下は、日付が常にYMDHMSの順序で、「HMS」部分のすべてまたは一部がオプションであることがわかっているアプリケーションに使用する関数です。区切り文字(たとえば、「2009-02-15」または「2009.02.15」)を受け入れます。対応するUNIX時間(1970-01-01 00:00:00 GMTからの秒数)を返すか、解析できなかった場合は-1を返します(つまり、1969- 12-31 23:59:59)。また、2桁の年XXから「69」までは「20XX」を指し、それ以外の場合は「19XX」を意味します(たとえば、「50-02-15」は2050-02-15を意味しますが、「75-02-15」は1975- 02-15)。

use Time::Local;

sub parsedate { 
  my($s) = @_;
  my($year, $month, $day, $hour, $minute, $second);

  if($s =~ m{^\s*(\d{1,4})\W*0*(\d{1,2})\W*0*(\d{1,2})\W*0*
                 (\d{0,2})\W*0*(\d{0,2})\W*0*(\d{0,2})}x) {
    $year = $1;  $month = $2;   $day = $3;
    $hour = $4;  $minute = $5;  $second = $6;
    $hour |= 0;  $minute |= 0;  $second |= 0;  # defaults.
    $year = ($year<100 ? ($year<70 ? 2000+$year : 1900+$year) : $year);
    return timelocal($second,$minute,$hour,$day,$month-1,$year);  
  }
  return -1;
}
20
dreeves

DateTime モジュールを使用している場合、Unix時間と考えるので、DateTimeオブジェクトで Epoch() メソッドを呼び出すことができます。

DateTimesを使用すると、Epochから日付オブジェクトにかなり簡単に変換できます。

別の方法として、 localtime とgmtimeはエポックを日月と年を含む配列に変換し、timelocalとtimegmの Time :: Localモジュール は反対に変換し、エポックへの時間要素(秒、分、...、日、月など)の配列。

34
SpoonMeiser

日付を解析するには、CPANで Date :: Parse を見てください。

17
bmdhacks

これは古い質問ですが、別の答えを提供すると思いました。

Time::Piece はPerl 5.9.5のコアです

これにより、strptimeメソッドを介して任意の形式で時間を解析できます。

例えば。:

my $t = Time::Piece->strptime("Sunday 3rd Nov, 1943",
                              "%A %drd %b, %Y");

便利な部分は-オーバーロードされたオブジェクトであるため、数値比較に使用できます。

例えば.

if ( $t < time() ) { #do something }

または、文字列コンテキストでアクセスする場合:

print $t,"\n"; 

あなたが得る:

Wed Nov  3 00:00:00 1943

さまざまな他の便利な時間ベースの変換を可能にする多数のアクセサメソッドがあります。 https://metacpan.org/pod/Time::Piece

7
Sobrique
$ENV{TZ}="GMT";
POSIX::tzset();
$time = POSIX::mktime($s,$m,$h,$d,$mo-1,$y-1900);
7
ysth

CPANからDate :: Manipを取得 、その後:

use Date::Manip;
$string = '18-Sep-2008 20:09'; # or a wide range of other date formats
$unix_time = UnixDate( ParseDate($string), "%s" );

編集:

Date :: Manipは大きくて遅いですが、解析には非常に柔軟で、純粋なPerlです。コードを書いているときに急いでいて、それを実行しているときに急いでいないことがわかっている場合に使用します。

例えば起動時にコマンドラインオプションを1回解析するために使用しますが、ビジーなWebサーバー上の大量のデータの解析には使用しないでください。

著者のコメント を参照してください。

(以下の最初のコメントの著者に感謝します)

6
scottc

CPANの助けを借りても借りなくても、「それを行う方法は1つではありません」の良い例の1つでしょう。

「日付/時刻」として渡されるものを制御できる場合は、特定のDate :: Time :: Formatサブクラスを使用するか、DateTimeを使用して、 DateTime ルートに進むことをお勧めします。 :: Format :: Strptimeは、おかしな日付形式をサポートするものがない場合(詳細は datetime FAQ をご覧ください)。一般に、Date :: Timeは、結果に対して何か深刻なことをしたい場合に使用する方法です。CPANのいくつかのクラスは、肛門保持的であり、非常に正確です。

奇妙な自由形式のものを期待している場合は、 Date :: Parse のstr2time()メソッドに投げてください。 、 Date :: Manip のオーバーヘッドなし。

2
Penfold

私のお気に入りの日時パーサーは DateTime :: Format :: ISO8601 動作するようになったら、Epoch()でEpoch秒に簡単に変換できるDateTimeオブジェクトが得られます

2
skiphoppy

CPANには多くの日付操作モジュールがあります。私のお気に入りは DateTime で、 strptime modules を使用して任意の形式の日付を解析できます。 CPANには、特殊な日付形式を処理するためのDateTime :: Formatモジュールも多数ありますが、strptimeが最も一般的です。

2
Shlomi Fish

さらに参照するために、例えば!#/bin/shスクリプト。

Epoch="`Perl -e 'use Time::Local; print timelocal('${SEC}','${MIN}','${HOUR}','${DAY}','${MONTH}','${YEAR}'),\"\n\";'`"

8進数値を避けることを忘れないでください!

2
Anders