날짜 이동이 예상대로 작동하지 않음

날짜 이동이 예상대로 작동하지 않음

다음 형식의 레코드가 있는 파일이 있습니다.

D20220327,S2927,977,1

D20220328,S2927,977,1

D20220329,S2927,977,1

D20220330,S2927,977,1

D20220331,S2927,977,1

D20220401,S2927,977,1

D20220402,S2927,977,1

D20220403,S2927,977,1

D20220404,S2927,977,1

그러나 이를 과거 7일로 변경하는 변환을 적용한 후 3월 28일부터 4월 3일까지의 날짜에는 작동하지 않습니다. 그러나 동일한 코드 논리는 3월 27일과 4월 4일에 제대로 작동합니다. 왜 이것이 일주일 동안만 작동하지 않는지 알 수 없습니다. 이것이 출력이다

D20220320,S2927,977,1 -- correct

D20220320,S2927,977,1 -- incorrect 

D20220321,S2927,977,1 -- incorrect

D20220322,S2927,977,1 -- incorrect

D20220323,S2927,977,1 -- incorrect

D20220324,S2927,977,1 -- incorrect

D20220325,S2927,977,1 -- incorrect

D20220326,S2927,977,1 -- incorrect

D20220328,S2927,977,1 -- correct

여기에 사용된 논리는 다음과 같습니다.

    BEGIN {
        OFS = FS = ","
}

{
        t = mktime(sprintf("%4d %.2d %.2d 00 00 00",
                substr($1,2,4),
                substr($1,6,2),
                substr($1,8,2)));

        $1 = substr($1,1,1) strftime("%Y%m%d", t - 7*24*60*60)

        print
}

답변1

귀하의 계산은 현지 시간으로 이루어지며 3월 27일 일광 절약 시간제 전환으로 인해 영향을 받습니다.

대신 UTC 시간(Unix 타임스탬프는 현지 시간이 아님)으로 계산하려면 최신 GNU 릴리스를 사용하여 추가 항목을 마지막 인수로 awk전달해야 합니다 .1mktime()

t = mktime(sprintf("%4d %.2d %.2d 00 00 00",
        substr($1,2,4),
        substr($1,6,2),
        substr($1,8,2)), 1);

awk이는 GNU awk릴리스 4.2.0+ 에서 사용 가능한 GNU 확장입니다 .

대안으로 자정(UTC) 주변 시간을 참조 시간으로 사용하지 않을 수 있습니다.

t = mktime(sprintf("%4d %.2d %.2d 12 00 00",
        substr($1,2,4),
        substr($1,6,2),
        substr($1,8,2)));

이렇게 하면 이전 GNU 구현과 필요한 기능이 있는 awk다른 구현에서 작동하게 됩니다 .awk

또 다른 대안은 변경된 현지 시간대로 스크립트를 실행하는 것입니다.

TZ=UTC awk -f script.awk inputfile

그러면 스크립트 실행을 위해 TZ환경 변수가 으로 설정되어 및 관련 기능 에서 사용되는 시간대가 변경됩니다 .UTCawkmktime()

답변2

Raku(이전의 Perl_6) 사용

raku -pe 's/^ D <( (\d**4)(\d**2)(\d**2) )> \, /{ "$0-$1-$2".Date.earlier(:7days).Str.subst("-", :g); }/;'

샘플 입력(빈 줄이 제거됨):

D20220327,S2927,977,1
D20220328,S2927,977,1
D20220329,S2927,977,1
D20220330,S2927,977,1
D20220331,S2927,977,1
D20220401,S2927,977,1
D20220402,S2927,977,1
D20220403,S2927,977,1
D20220404,S2927,977,1

샘플 출력:

D20220320,S2927,977,1
D20220321,S2927,977,1
D20220322,S2927,977,1
D20220323,S2927,977,1
D20220324,S2927,977,1
D20220325,S2927,977,1
D20220326,S2927,977,1
D20220327,S2927,977,1
D20220328,S2927,977,1

간단히 말해서 Raku의 라인별(자동 인쇄) -pe플래그가 익숙한 연산자와 함께 사용됩니다 s///. 숫자는 일치 변수 $0, $1및 괄호 로 캡처되며 $2캡처 마커는 <( … )>일치의 다른 모든 요소를 ​​삭제하는 데 사용됩니다.

대체에서 Raku는 { … }블록 내부에서 코드를 실행합니다. $0, $1및 캡처 $2는 적절한 대시( )로 문자열화되며 이 문자열은 메서드를 호출할 수 있는 개체 -로 인식됩니다 . [참고: 일부 사용자는 쓰기가 더 친숙한 구문이라고 생각할 수 있습니다 . 어느 쪽이든 작동합니다]. 개체가 7일로 다시 설정 되면 개체가 -ingified되어 반환 시 대시( )를 제거하는 데 사용됩니다 .Dateearlier(:7days)earlier(days => 7)DateStrsubst-

https://docs.raku.org/routine/Date
https://docs.raku.org/routine/Dateish
https://raku.org

관련 정보