2008-09-18 5 views
36

(년, 월, 일,시, 분, 초)의 배열로 날짜/시간이 주어지면 1970-01-01 00:00 이후의 초 수와 같이 시간을 어떻게 에포크 시간으로 변환하겠습니까? 00 GMT?Perl에서 날짜/시간을 에포크 시간 (1970 년 이후 유닉스 시간/초)으로 변환하려면 어떻게해야합니까?

보너스 질문 : 날짜/시간이 문자열로 주어지면 어떻게 그것을 (y, m, d, h, m, s) 배열로 파싱 하시겠습니까?

+1

이 질문에 유래 stackoverflow.com 의해 질문 – jdelator

+2

필수주의 사항 : 1901 년 -2038 년에만 유닉스 Epoch 정의됩니다. – Piskvor

+5

@Piskvor : 그건 사실이 아닙니다. 그리고 그 시대는 1970 년 1 월 1 일이 아닌 범위로 정의됩니다. 그러나 그것은 32 비트 정수로 나타낼 경우 유닉스 타임 스탬프에 대해 얻을 수있는 가장 좋은 범위입니다 (광범위한 규칙). –

답변

19

이것은 유닉스 시간을 얻을 수있는 간단한 방법입니다 :

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

주 인수의 역순 월 그 달 0 은 CPAN에서 DateTime 모듈을 참조하십시오 더 많은 옵션을 보려면이다.

구문 분석에 대해서는 CPAN의 Date::Parse 모듈을 참조하십시오. 당신이 진짜로 파싱에 대해 궁금증을 갖기를 원한다면 Date::Manip이 도움이 될 수 있습니다. 그러나 많은 수하물 (예 : 일반적인 업무 휴일과 같은 것들을 알고 있습니다)을 가지고 있기 때문에 자체 문서가 당신에게 경고합니다. 빠릅니다.

구문 분석 할 날짜/시간 형식에 대해 알고있는 경우 간단한 정규식으로 충분할 수 있지만 적절한 CPAN 모듈을 사용하는 것이 더 나을 것입니다. 예를 들어 날짜가 항상 YMDHMS 순서로 표시된다면 CPAN 모듈 DateTime::Format::ISO8601을 사용하십시오. 다른 건 몰라도 내 자신 참고로


, 아래 내가 날짜는 항상 선택은 "HMS"부분의 전부 또는 일부에 YMDhms와 순서에있을 것입니다 확인 된 응용 프로그램에 사용하는 기능입니다. 구분 기호를 사용할 수 있습니다 (예 : "2009-02-15"또는 "2009.02.15"). 해당 유닉스 시간 (1970-01-01 00:00:00 GMT 이후의 초)을 반환하거나 구문 분석 할 수없는 경우 -1을 반환합니다. 이는 1969 년 날짜를 구문 분석 할 필요가 전혀 없음을 의미합니다. 12-31 23:59:59). 또한 "69XX"(예 : "50-02-15"는 2050-02-15를 의미하지만 "75-02-15"는 1975 년을 의미 함)는 "20XX"를 나타내는 두 자리 연도 XX를 "69" 02-15). 당신이 DateTime 모듈을 사용하는 경우 그건 당신이 유닉스 시간으로 어떻게 생각하는지 이후

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; 
} 
+0

Time :: Local은 어떤 점에서 POSIX (strftime)이 더 일반적이지 않은 이점이 있습니까? –

+3

strftime은 시간을 출력하기위한 것이고, timelocal은 그것들을 '입력'하는 것입니다. –

+1

제로 인덱스 달에 $ month-1 !!!!!! 나는 그 것을 다시는 잊지 않으려 고 노력할 것이다. –

33

, 당신은 DateTime 개체에 epoch() 메서드를 호출 할 수 있습니다.

DateTimes를 사용하면 에포크에서 날짜 개체로 쉽게 변환 할 수 있습니다.

대체로, localtime이고 gmtime은 일년 월과 일을 포함하는 배열로 변환하고 Time::Local module의 timelocal과 timegm은 시간 요소 (초, 분, ..., 일)의 배열을 반대로 변환합니다. , 달 등)을 신 (新) 시대로 변화시킨다.

+0

자신의 (버그가있는) 솔루션을 굴리는 것보다 일반적인 작업을 수행하는 라이브러리 함수를 사용하는 것이 항상 좋습니다. –

+0

DateTime이 표준 펄 설치 –

-4

다른 기능에서 호출되는 것이 아닌 명령 줄 유틸리티를 찾는 경우이 스크립트를 사용해보십시오. 그것은 (거의 모든 리눅스 시스템에 존재) GNU 날짜의 존재를 가정

#! /usr/bin/perl -w 

use strict; 

$_ = (join ' ', @ARGV); 
$_ ||= <STDIN>; 

chomp; 

if (/^[\d.]+$/) { 
    print scalar localtime $_; 
    print "\n"; 
} 
else { 
    exec "date -d '$_' +%s"; 
} 

여기 그것이 작동하는 방법은 다음과 같습니다

$ Time now 
1221763842 

$ Time yesterday 
1221677444 

$ Time 1221677444 
Wed Sep 17 11:50:44 2008 

$ Time '12:30pm jan 4 1987' 
536790600 

$ Time '9am 8 weeks ago' 
1216915200 
+0

의 일부가 아니기 때문에 아래의 'timelocal'솔루션이 더 좋습니다. 쉘 스크립트이거나, 적절한 Perl 모듈을 사용하여 작업해야하는 것입니다. IMHO . –

+0

왜 그것을 쉘 스크립트로 다시 작성합니까? 그것은 그대로 잘 작동하며 매일 유용하게 사용할 수 있습니다. – raldi

+0

시스템 날짜 명령을 사용하는 경우 perl 솔루션이 아닙니다. 유닉스 나 윈도우에서는 작동하지 않습니다. – kkoolpatz

-3

다양한 ISO 관련 형식의 날짜를 변환하는 필터 (Mighty Kuhn의 the writings을 읽은 후 다른 사람을 사용하고 싶습니까?)에 표준 입력에 초 - 이후 - 더 - 시대를 표준 출력에 시간이 두 부분을 설명하는 역할을 수 있습니다

[email protected]:~$ cat `which isoToEpoch` 
#!/usr/bin/perl -w 
use strict; 
use Time::Piece; 
# sudo apt-get install libtime-piece-perl 
while (<>) { 
    # date --iso=s: 
    # 2007-02-15T18:25:42-0800 
    # Other matched formats: 
    # 2007-02-15 13:50:29 (UTC-0800) 
    # 2007-02-15 13:50:29 (UTC-08:00) 
    s/(\d{4}-\d{2}-\d{2}([T ])\d{2}:\d{2}:\d{2})(?:\.\d+)? ?(?:\(UTC)?([+\-]\d{2})?:?00\)?/Time::Piece->strptime ($1, "%Y-%m-%d$2%H:%M:%S")->epoch - (defined ($3) ? $3 * 3600 : 0)/eg; 
    print; 
} 
[email protected]:~$ 
2

내가 가장 좋아하는 날짜 파서 DateTime::Format::ISO8601 당신이 작업을했으면, 당신은 날짜 시간을 가질 것입니다 객체는 쉽게 convertable는, 시대와 초()

6

Get Date::Manip from CPAN을 획기적인하기 :

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

편집 :

날짜 : Manip 난을 크고 느리지 만 파싱에는 매우 유연하며 순수한 perl입니다. 코드를 작성할 때 서둘러서 사용하고 있으며, 코드를 실행할 때 서둘러서는 안된다는 것을 알고 있습니다.

시작시 명령 행 옵션을 구문 분석 할 때이 옵션을 사용하지만 사용량이 많은 웹 서버에서 많은 양의 데이터를 구문 분석하지 마십시오.

the authors comments을 참조하십시오. 또는 CPAN의 도움없이 아마

+6

아니요, 제발하지 마십시오. Date :: Manip 자신의 문서에는 그것을 사용하지 말라고 설득하는 큰 부분이 있습니다. –

+2

Date : 당신이 가장 약할 때 Manip이 당신을 배반 할 것입니다. DateTime을 사용하십시오. :) – Kevin

+0

@AristotlePagaltzis, "당신이 그것을 사용하지 말라고 설득하려한다"는 말은 오직 하나의 캘린더로 모든 것을 할 수 있다고 말하지만, 여러 개의 다른 모듈에 의해보다 효율적으로 수행 될 수 있습니다. " 그래서, scottc은 이미 말했듯이, Date :: Manip을 더욱 강조하여 원 스톱 솔루션입니다. –

2

이 세상에는 한 가지 방법이 '의 좋은 예 중 하나 "

(아래 첫번째 댓글 작성자에게 감사).

하는 경우 특정 날짜 :: 시간 :: 형식 하위 클래스를 사용하거나 DateTime :: Format :: Strptime을 사용하여 DateTime 경로를 사용하여 '날짜/시간'으로 전달할 항목을 제어 할 수 있습니다. 귀하의 이상한 날짜 형식을 지원하지 않습니다 (자세한 내용은 datetime FAQ 참조). 일반적으로 Date :: Time은 결과에 심각한 결과를 보이고 싶다면 갈 방법입니다 : CPAN에 대한 몇 개의 클래스는 항문 - 보속적이고 사로 잡힌 적극적으로 정확합니다.

이상한 프리폼을 원한다면 Date::Parse의 str2time() 메소드에 던져 넣으십시오. 그러면 초당 시간 값을 얻을 수 있습니다. 그러면 Date::Manip의 오버 헤드없이 사악한 방법을 사용할 수 있습니다. .

2

CPAN에는 많은 날짜 처리 모듈이 있습니다. 내가 가장 좋아하는 것은 DateTime이고, strptime modules을 사용하면 날짜를 임의의 형식으로 파싱 할 수 있습니다. 특별한 날짜 형식을 처리하기 위해 CPAN에는 많은 DateTime :: Format 모듈이 있지만 strptime이 가장 일반적입니다. 상기 참고 용

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

획기적인 시간은 이미 GMT이며, 시간대가 없습니다. TZ = GMT를 명시 적으로 설정하면 현지 날짜/시간이 아닌 ** GMT 시간대에서 ** 시간을 파싱하지 않습니까? (그리고 TZ = UTC, GMT는 국가의 시간대입니다.) –

+0

@ ThomasGuyot-Sionnest 제 의도는 mktime이 현지 시간에서 초까지 초를 변환한다는 것을 보여주기위한 것이 었습니다. 그래서 현지 시간 입력이 무엇인지 알아야합니다. 그에 따라 TZ를 설정하십시오. (또는 TZ가 이미 원하는대로 설정되었다고 가정합니다. 그러나 그다지 유익하지 않습니다.) – ysth

+0

저는 대부분의 사람들이 현지 시간을 사용하기를 원하고 컴퓨터/서버에 설정된 것으로 가정하는 것이 안전하다고 생각합니다. 다른 지역에서 작업 할 때는 영역이 중요하다는 것을 이해하지만 실제로 GMT에 TZ로 설정하면 TZ가 실제 답변에서 벗어나고 루키를 잘못 입력하여 시간 입력에 잘못 사용될 수 있다고 생각합니다. OTOH TZ를 변경 한 후 tzset()을 호출하면 보너스 포인트가 생깁니다.) –

2

, 적용 예를 들어, 스크립트 !#/bin/sh 수있는 하나의 라이너.

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

그냥 8 진수 값을 사용하지 마십시오.

+0

무한히 유연한 GNU 날짜를 사용할 수있는 이유는 무엇입니까? 'date -d "STRING"+ % s "은"어제 "에서"90 일 "까지 (지금 당장) 거의 모든 것을"Mar 15 2016 "과 같은 더 전통적인 것들로 허용하고 거의 모든 형식으로 출력 할 수 있습니다 (' + % s'은 신기원이다. 자세한 것은'date --help'를 보라). (너무 나쁜 perl'DateTime'은이 기능을 가지고 있지 않습니다.) –

7

나는 이것이 오래된 질문이지만, 나는 또 다른 대답을 줄 것이라고 생각했다.

Time::Piece 이것은 strptime 방법을 통해, 임의의 포맷으로 시간의 해석을 허용 펄 5.9.5

로의 핵심이다.

예컨대 :

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

관련 문제