날짜 변환이 예상대로 작동하지 않습니다.

날짜 변환이 예상대로 작동하지 않습니다.

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

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추가 인수를 1마지막 인수로 전달해야 합니다 mktime().

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

이는 GNU 버전 4.2.0+ awk에서 사용 가능한 GNU 확장 입니다.awk

대안으로 자정(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. [참고: 일부 사용자는 더 친숙한 구문을 작성하는 것을 발견할 수 있습니다. 두 형식 모두 유효합니다.] 객체가 7일로 다시 설정되면 기호로 표시되어 반환 시 대시( )를 제거하는 데 사용됩니다.$1$2-Dateearlier(:7days)earlier(days => 7)DateStrsubst-

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

관련 정보