如何使 awk 能够感知时区?

如何使 awk 能够感知时区?

时间戳(通俗地说) 可以是一个 ISO8601 字符串(通常是 POSIX 指定格式的输出%FT%T),并添加了一个区域字符串(宽松地说,是 date 中可用的两种格式之一,或者%Z%z)。

然后,时间戳字符串变成特定的“时间点”,即不具有未定义的本地时间(具有至少24个不同的可能的不同值)。

这样的“时间点”字符串可以转换为纪元值(格式的结果+'%s'),而不会丢失信息。

例如,输入位于第 1 列和第 2 列,输出位于第 3 列和第 4 列:

$ cat indate
2020-03-02T12:23:34 UTC         1583151814  2020-03-02T06:23:34CST-0600
2020-03-02T12:23:34 Z           1583151814  2020-03-02T06:23:34CST-0600
2020-03-02T12:23:34 EST         1583169814  2020-03-02T11:23:34CST-0600
2020-03-02T12:23:34 CST         1583173414  2020-03-02T12:23:34CST-0600
2020-03-02T12:23:34 AST         1583166214  2020-03-02T10:23:34CST-0600
2020-03-02T12:23:34 ADT         1583162614  2020-03-02T09:23:34CST-0600
2020-03-02T12:23:34 EDT         1583166214  2020-03-02T10:23:34CST-0600
2020-03-02T12:23:34 BST         1583148214  2020-03-02T05:23:34CST-0600
2020-03-02T12:23:34 IST         1583132014  2020-03-02T00:53:34CST-0600
2020-03-02T12:23:34 +00:00      1583151814  2020-03-02T06:23:34CST-0600
2020-03-02T12:23:34 -0400       1583166214  2020-03-02T10:23:34CST-0600
2020-03-02T12:23:34 -0800       1583180614  2020-03-02T14:23:34CST-0600
2020-03-02T12:23:34 +06:00      1583130214  2020-03-02T00:23:34CST-0600

请求的输出应该是自纪元以来的秒数,同时考虑时区和(如果可能)用%Z%z值重写的时间戳。

众所周知,GNU date 能够在第 1 列和第 2 列上自行处理所有这些:

$ date -f indate +%s

问题是:awk 有解决方案吗?

我能够得到它的唯一方法在 AWK 中是通过使用 GNU 日期,这涉及大量的重新格式化,为每个新行调用外部可执行文件并将其返回到 awk。我相信有一种方法只能调用一次 date,但那仍然是一个外部可执行文件。

有没有更好的办法用 awk

我写的awk脚本:

$ cat tst.awk
#!/bin/bash
awk 'BEGIN{FS="[ \t:T-]*"}
     {

        cmd="date -d '\''"$1 $2"'\'' +'\''%s'\''";
        while ( ( cmd | getline fmtDate) > 0 ) {
            val = fmtDate
        }
        close(cmd);

        datestr=$1" "$2" "$3" "$4" "$5" "$6" 0 "
        print mktime(datestr),$1,$2,"\t",cmd,"\t",val

    }'  indate

并且,输出似乎是正确的(对于美国东部时间当地时间):

$ ./tst.awk
1607012614 2020-12-03T12:23:34 UTC  date -d '2020-12-03T12:23:34 UTC' +'%s' 1606998214
1607012614 2020-12-03T12:23:34 Z    date -d '2020-12-03T12:23:34 Z' +'%s'   1606998214
1607012614 2020-12-03T12:23:34 EST  date -d '2020-12-03T12:23:34 EST' +'%s' 1607016214
1607012614 2020-12-03T12:23:34 EDT  date -d '2020-12-03T12:23:34 EDT' +'%s' 1607012614
1607012614 2020-12-03T12:23:34 BST  date -d '2020-12-03T12:23:34 BST' +'%s' 1606994614
1607012614 2020-12-03T12:23:34 IST  date -d '2020-12-03T12:23:34 IST' +'%s' 1606978414
1607012614 2020-12-03T12:23:34 +00:00   date -d '2020-12-03T12:23:34 +00:00' +'%s'  1606998214
1607012614 2020-12-03T12:23:34 -0400    date -d '2020-12-03T12:23:34 -0400' +'%s'   1607012614
1607012614 2020-12-03T12:23:34 -0800    date -d '2020-12-03T12:23:34 -0800' +'%s'   1607027014
1607012614 2020-12-03T12:23:34 +06:00   date -d '2020-12-03T12:23:34 +06:00' +'%s'  1606976614

答案1

以下是关于各种扩展的 GNU awk 的全部内容,它了解您环境中的时区,但不直接了解您数据中的时区。

它并不完全是您想要的输出(如果您的所有 TZ 值都是可移植的,特别是 EDT、BST 和 IST,或者需要任何额外的处理以 awk 喜欢的 TZ 格式,我不知道 - 您必须进一步调查)但您可以在下面看到我们正在使用 TZ 来影响自纪元输出以来的秒数:

$ gawk '{
    dt = gensub(/\s+\S+$/,"",1); gsub(/[-:T]/," ",dt)
    tz = $NF
    if ( match(tz,/^([-+]?)([0-9]{2}):?([0-9]{2})$/,a) ) {
        tz = (a[1] == "-" ? "+" : "-") a[2] ":" a[3]
    }
    ENVIRON["TZ"] = tz

    epochSecs = mktime(dt)

    ENVIRON["TZ"] = "UTC"
    printf "%-30s ->  %10s  ->  %s UTC\n", $0, epochSecs, strftime("%F %T",epochSecs)
}' indate
2020-12-03T12:23:34 UTC        ->  1606998214  ->  2020-12-03 12:23:34 UTC
2020-12-03T12:23:34 Z          ->  1606998214  ->  2020-12-03 12:23:34 UTC
2020-12-03T12:23:34 EST        ->  1607016214  ->  2020-12-03 17:23:34 UTC
2020-12-03T12:23:34 EDT        ->  1606998214  ->  2020-12-03 12:23:34 UTC
2020-12-03T12:23:34 BST        ->  1606998214  ->  2020-12-03 12:23:34 UTC
2020-12-03T12:23:34 IST        ->  1606998214  ->  2020-12-03 12:23:34 UTC
2020-12-03T12:23:34 +00:00     ->  1606998214  ->  2020-12-03 12:23:34 UTC
2020-12-03T12:23:34 -0400      ->  1607012614  ->  2020-12-03 16:23:34 UTC
2020-12-03T12:23:34 -0800      ->  1607027014  ->  2020-12-03 20:23:34 UTC
2020-12-03T12:23:34 +06:00     ->  1606976614  ->  2020-12-03 06:23:34 UTC

以上依赖于mktime()(并且strftime()只是为了从派生纪元秒输出 UTC 时间,以便于比较时间戳)使用TZ环境变量的值以及能够更改TZ正在运行的 awk 脚本环境中的值从需要 GNU awk 版本 4.2 或更高版本的脚本内部。

请注意,对于输入中末尾带有数字的日期(例如 )2020-12-03T12:23:34 +06:00,日期不用作+06:00时区,而是将其用作人类可读的增量,应用于以 UTC 形式提供的时间戳。如果使用date -d '2020-12-03T12:23:34 +06:00' +'%s'(whichoutputs 1606976614.which is 2020-12-03T12:23:34 UTC- 6 小时) 与TZ='+06:00' date -d '2020-12-03T12:23:34' +'%s'(whichoutputs 1607019814,which is 2020-12-03T12:23:34 UTC+ 6 小时),你可以看到差异。

因此,我们必须交换上面的符号tz,使其以与date处理它相同的方式处理,即在将其视为 UTC 后应用于时间戳的增量,而不是将其视为实际时区。

有趣的是,date当时区是在 TZ 中设置的,而不是作为时间戳字符串的一部分提供时,在处理 EDT、BST 和 IST 时区方面,其行为与 gawk 相同,但它也可以理解地在处理:中没有 a 的数值时失败。设置为 TZ 时居中:

$ while read -r ts tz; do
    printf '%s:\t %s  vs  %s\n' "$tz" "$(date +'%s' -d"$ts $tz")" $(TZ="$tz" date '+%s' -d"$ts")
done < indate
UTC:     1606998214  vs  1606998214
Z:   1606998214  vs  1606998214
EST:     1607016214  vs  1607016214
EDT:     1607012614  vs  1606998214
BST:     1606994614  vs  1606998214
IST:     1606978414  vs  1606998214
+00:00:  1606998214  vs  1606998214
-0400:   1607012614  vs  1606998214
-0800:   1607027014  vs  1606998214
+06:00:  1606976614  vs  1607019814

因此,除了读取时区之外,似乎还有一些魔力date -d,这是有道理的,因为它在手册页asmostly free format human readable date string和 可以包含诸如 之类的字符串next Thursday

当然,您可以编写一个像这样的 awk 脚本,将数据中使用的不可移植 TZ 值映射到可移植值(请参阅https://vdc-repo.vmware.com/vmwb-repository/dcr-public/790263bc-bd30-48f1-af12-ed36055d718b/e5f17bfc-ecba-40bf-a04f-376bbb11e811/timezone.htmlhttps://en.wikipedia.org/wiki/List_of_tz_database_time_zones):

$ gawk 'BEGIN {
    tzmap["EST"] = "US/Eastern"
    tzmap["EDT"] = "-04:00"
    tzmap["BST"] = "+01:00"
    tzmap["IST"] = "Asia/Calcutta"
}
{
    dt = gensub(/\s+\S+$/,"",1); gsub(/[-:T]/," ",dt)
    tz = ( $NF in tzmap ? tzmap[$NF] : $NF )
    if ( match(tz,/^([-+]?)([0-9]{2}):?([0-9]{2})$/,a) ) {
        tz = (a[1] == "-" ? "+" : "-") a[2] ":" a[3]
    }
    ENVIRON["TZ"] = tz

    epochSecs = mktime(dt)

    ENVIRON["TZ"] = "UTC"
    printf "%-30s ->  %10s  ->  %s UTC\n", $0, epochSecs, strftime("%F %T",epochSecs)
}' indate
2020-12-03T12:23:34 UTC        ->  1606998214  ->  2020-12-03 12:23:34 UTC
2020-12-03T12:23:34 Z          ->  1606998214  ->  2020-12-03 12:23:34 UTC
2020-12-03T12:23:34 EST        ->  1607016214  ->  2020-12-03 17:23:34 UTC
2020-12-03T12:23:34 EDT        ->  1607012614  ->  2020-12-03 16:23:34 UTC
2020-12-03T12:23:34 BST        ->  1606994614  ->  2020-12-03 11:23:34 UTC
2020-12-03T12:23:34 IST        ->  1606978414  ->  2020-12-03 06:53:34 UTC
2020-12-03T12:23:34 +00:00     ->  1606998214  ->  2020-12-03 12:23:34 UTC
2020-12-03T12:23:34 -0400      ->  1607012614  ->  2020-12-03 16:23:34 UTC
2020-12-03T12:23:34 -0800      ->  1607027014  ->  2020-12-03 20:23:34 UTC
2020-12-03T12:23:34 +06:00     ->  1606976614  ->  2020-12-03 06:23:34 UTC

您只需要提前知道哪些 TZ 可以出现在您的输入文件中,您似乎会出现这一情况。

注意:以上命令是在 Mac 上运行的。在 cygwin 中运行相同的命令时,或无法TZ理解任何数值。我怀疑这是一个 cygwin 问题,而不是任何其他类型的可移植性问题。dateawk

与大家讨论后时区数据库提供商 Paul Eggert,我编写了一个 shell 脚本,它使用 bash 加上 POSIX 工具生成一个从时区缩写到偏移量和数据库名称的映射文件(如果您有时区数据库目录结构和正确的工具版本)zdump

$ cat maptzabbrs
#!/usr/bin/env bash

usage() {
    cat <<'!'
Usage:  maptzabbrs [overrides]
        maptzabbrs --help

Given a timezone database directory like /usr/share/zoneinfo/posix and
a version of zdump (https://man7.org/linux/man-pages/man8/zdump.8.html)
that supports "-i", this will output a tab-separated table of
Abbreviation -> Offset -> Database Names where the list of Database Names
associated with each Abbreviation+Offset will be comma-separated.
Database names without an alphanumeric abbreviation are ignored.

Input: "zdump -i" outputs blank line separated records like:

        TZ="/usr/share/zoneinfo/posix/America/Chicago"
        -       -       -06     CST
        2022-03-13      03      -05     CDT     1
        2022-11-06      01      -06     CST

        TZ="/usr/share/zoneinfo/posix/Asia/Hong_Kong"
        -       -       +08     HKT

Stdout Output (all alphanumeric abbreviations):

        CDT     -04:00  America/Havana,Cuba
        CDT     -05:00  America/Bahia_Banderas,America/Chicago,...
        CST     +08:00  Asia/Chongqing,Asia/Chungking,...
        CST     -05:00  America/Havana,Cuba
        CST     -06:00  America/Bahia_Banderas,...,America/Chicago,...
        HKT     +08:00  Asia/Hong_Kong,Hongkong

Stderr Output (only abbreviations with multiple offsets):

        Warning: abbreviation(s) with multiple alternative offsets:
        CDT     -04:00  America/Havana,Cuba
        CDT     -05:00  America/Bahia_Banderas,America/Chicago,...
        CST     +08:00  Asia/Chongqing,Asia/Chungking,...
        CST     -05:00  America/Havana,Cuba
        CST     -06:00  America/Bahia_Banderas,...,America/Chicago,...

If this tool is called with an argument, that is taken as file of overrides
to disambiguate abbreviations such as the above that would otherwise have
multiple offsets, e.g. if the file "overrides" contained (third column
optional and ignored):

        CDT     -05:00  America/Bahia_Banderas,America/Chicago,...
        CST     -06:00  America/Bahia_Banderas,...,America/Chicago,...

Then calling the tool as

        maptzabbrs overrides

would restrict the stdout for CST and CDT to only be for the stated
offsets and they would not be reported as ambiguous on stderr.

References:
        https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
        https://en.wikipedia.org/wiki/Tz_database

Thanks to the TZ dabatase provider Paul Eggert for background
information and suggestions on how to make this work.
!
}

if [[ "$1" == "--help" ]]; then
    usage
    exit
fi

: tzDir=${tzDir:='/usr/share/zoneinfo/posix'}
(( $# > 0 )) && overrides=$1 || overrides='/dev/null'

ofs='\t'
printf "Zone${ofs}Offset${ofs}Names\n"

find "$tzDir" -type f | sort | xargs zdump -c 2022,2023 -i |
awk -v tzDir="$tzDir" -v OFS="$ofs" '
    FILENAME == ARGV[1] {
        abbr2offset[$1] = $2
        next
    }
    NF {
        if ( sub(/^TZ="/,"") ) {
            sub(/".*/,"")
            name = substr($0,length(tzDir)+2)
        }
        else {
            # change [[:alpha:]] to [[a-zA-Z]] if not supported
            abbr = ($4 ~ /[[:alpha:]]/ ? $4 : "")
            offset = sprintf("%s:%02d",substr($3,1,3),substr($3,4))

            if ( abbr != "" ) {
                abbrs[abbr]
                if ( !(abbr in abbr2offset) ||
                     ((abbr in abbr2offset) && (abbr2offset[abbr] == offset)) ) {
                    if ( !seen_offset[abbr,offset]++ ) {
                        abbrsOffsets[abbr,++numOffsets[abbr]] = offset
                    }
                    if ( !seen_name[abbr,offset,name]++ ) {
                        abbrsNames[abbr,offset,++numNames[abbr,offset]] = name
                    }
                }
            }
        }
    }
    END {
        for ( abbr in abbrs ) {
            for ( offsetNr=1; offsetNr<=numOffsets[abbr]; offsetNr++ ) {
                offset = abbrsOffsets[abbr,offsetNr]
                for ( nameNr=1; nameNr<=numNames[abbr,offset]; nameNr++ ) {
                    name = abbrsNames[abbr,offset,nameNr]
                    names = (nameNr>1 ? names "," : "") name
                }
                print abbr, offset, names | "sort"

                if ( numOffsets[abbr] > 1 ) {
                    gotAmbiguous = 1
                    ambiguous[abbr OFS offset] = names
                }
            }
        }
        close("sort")

        if ( gotAmbiguous ) {
            print "Warning: abbreviation(s) with multiple alternative offsets:" | "cat>&2"
            close("cat>&2")
            for ( abbrOffset in ambiguous ) {
                print abbrOffset, ambiguous[abbrOffset] | "sort>&2"
            }
            close("sort>&2")
        }
    }
' "$overrides" -

考虑到这个覆盖文件,上面的代码应该需要大约半秒的时间来运行:

$ cat overrides
CDT     -05:00  America/Bahia_Banderas,America/Chicago,America/Indiana/Knox,America/Indiana/Tell_City,America/Knox_IN,America/Matamoros,America/Menominee,America/Merida,America/Mexico_City,America/Monterrey,America/North_Dakota/Beulah,America/North_Dakota/Center,America/North_Dakota/New_Salem,America/Rainy_River,America/Rankin_Inlet,America/Resolute,America/Winnipeg,CST6CDT,Canada/Central,Mexico/General,US/Central,US/Indiana-Starke
CST     -06:00  America/Bahia_Banderas,America/Belize,America/Chicago,America/Costa_Rica,America/El_Salvador,America/Guatemala,America/Indiana/Knox,America/Indiana/Tell_City,America/Knox_IN,America/Managua,America/Matamoros,America/Menominee,America/Merida,America/Mexico_City,America/Monterrey,America/North_Dakota/Beulah,America/North_Dakota/Center,America/North_Dakota/New_Salem,America/Rainy_River,America/Rankin_Inlet,America/Regina,America/Resolute,America/Swift_Current,America/Tegucigalpa,America/Winnipeg,CST6CDT,Canada/Central,Canada/Saskatchewan,Mexico/General,US/Central,US/Indiana-Starke
IST     +05:30  Asia/Calcutta,Asia/Kolkata
PST     -08:00  America/Ensenada,America/Los_Angeles,America/Santa_Isabel,America/Tijuana,America/Vancouver,Canada/Pacific,Mexico/BajaNorte,PST8PDT,US/Pacific

它在我的机器上产生了这个输出:

$ /maptzabbrs overrides
Zone    Offset  Names
ACDT    +10:30  Australia/Adelaide,Australia/Broken_Hill,Australia/South,Australia/Yancowinna
ACST    +09:30  Australia/Adelaide,Australia/Broken_Hill,Australia/Darwin,Australia/North,Australia/South,Australia/Yancowinna
ADT     -03:00  America/Glace_Bay,America/Goose_Bay,America/Halifax,America/Moncton,America/Thule,Atlantic/Bermuda,Canada/Atlantic
AEDT    +11:00  Antarctica/Macquarie,Australia/ACT,Australia/Canberra,Australia/Currie,Australia/Hobart,Australia/Melbourne,Australia/NSW,Australia/Sydney,Australia/Tasmania,Australia/Victoria
AEST    +10:00  Antarctica/Macquarie,Australia/ACT,Australia/Brisbane,Australia/Canberra,Australia/Currie,Australia/Hobart,Australia/Lindeman,Australia/Melbourne,Australia/NSW,Australia/Queensland,Australia/Sydney,Australia/Tasmania,Australia/Victoria
AKDT    -08:00  America/Anchorage,America/Juneau,America/Metlakatla,America/Nome,America/Sitka,America/Yakutat,US/Alaska
AKST    -09:00  America/Anchorage,America/Juneau,America/Metlakatla,America/Nome,America/Sitka,America/Yakutat,US/Alaska
AST     -04:00  America/Anguilla,America/Antigua,America/Aruba,America/Barbados,America/Blanc-Sablon,America/Curacao,America/Dominica,America/Glace_Bay,America/Goose_Bay,America/Grenada,America/Guadeloupe,America/Halifax,America/Kralendijk,America/Lower_Princes,America/Marigot,America/Martinique,America/Moncton,America/Montserrat,America/Port_of_Spain,America/Puerto_Rico,America/Santo_Domingo,America/St_Barthelemy,America/St_Kitts,America/St_Lucia,America/St_Thomas,America/St_Vincent,America/Thule,America/Tortola,America/Virgin,Atlantic/Bermuda,Canada/Atlantic
AWST    +08:00  Australia/Perth,Australia/West
BST     +01:00  Europe/Belfast,Europe/Guernsey,Europe/Isle_of_Man,Europe/Jersey,Europe/London,GB,GB-Eire
CAT     +02:00  Africa/Blantyre,Africa/Bujumbura,Africa/Gaborone,Africa/Harare,Africa/Juba,Africa/Khartoum,Africa/Kigali,Africa/Lubumbashi,Africa/Lusaka,Africa/Maputo,Africa/Windhoek
CDT     -05:00  America/Bahia_Banderas,America/Chicago,America/Indiana/Knox,America/Indiana/Tell_City,America/Knox_IN,America/Matamoros,America/Menominee,America/Merida,America/Mexico_City,America/Monterrey,America/North_Dakota/Beulah,America/North_Dakota/Center,America/North_Dakota/New_Salem,America/Rainy_River,America/Rankin_Inlet,America/Resolute,America/Winnipeg,CST6CDT,Canada/Central,Mexico/General,US/Central,US/Indiana-Starke
CEST    +02:00  Africa/Ceuta,Arctic/Longyearbyen,CET,Europe/Amsterdam,Europe/Andorra,Europe/Belgrade,Europe/Berlin,Europe/Bratislava,Europe/Brussels,Europe/Budapest,Europe/Busingen,Europe/Copenhagen,Europe/Gibraltar,Europe/Ljubljana,Europe/Luxembourg,Europe/Madrid,Europe/Malta,Europe/Monaco,Europe/Oslo,Europe/Paris,Europe/Podgorica,Europe/Prague,Europe/Rome,Europe/San_Marino,Europe/Sarajevo,Europe/Skopje,Europe/Stockholm,Europe/Tirane,Europe/Vaduz,Europe/Vatican,Europe/Vienna,Europe/Warsaw,Europe/Zagreb,Europe/Zurich,Poland
CET     +01:00  Africa/Algiers,Africa/Ceuta,Africa/Tunis,Arctic/Longyearbyen,CET,Europe/Amsterdam,Europe/Andorra,Europe/Belgrade,Europe/Berlin,Europe/Bratislava,Europe/Brussels,Europe/Budapest,Europe/Busingen,Europe/Copenhagen,Europe/Gibraltar,Europe/Ljubljana,Europe/Luxembourg,Europe/Madrid,Europe/Malta,Europe/Monaco,Europe/Oslo,Europe/Paris,Europe/Podgorica,Europe/Prague,Europe/Rome,Europe/San_Marino,Europe/Sarajevo,Europe/Skopje,Europe/Stockholm,Europe/Tirane,Europe/Vaduz,Europe/Vatican,Europe/Vienna,Europe/Warsaw,Europe/Zagreb,Europe/Zurich,Poland
CST     -06:00  America/Bahia_Banderas,America/Belize,America/Chicago,America/Costa_Rica,America/El_Salvador,America/Guatemala,America/Indiana/Knox,America/Indiana/Tell_City,America/Knox_IN,America/Managua,America/Matamoros,America/Menominee,America/Merida,America/Mexico_City,America/Monterrey,America/North_Dakota/Beulah,America/North_Dakota/Center,America/North_Dakota/New_Salem,America/Rainy_River,America/Rankin_Inlet,America/Regina,America/Resolute,America/Swift_Current,America/Tegucigalpa,America/Winnipeg,CST6CDT,Canada/Central,Canada/Saskatchewan,Mexico/General,US/Central,US/Indiana-Starke
ChST    +10:00  Pacific/Guam,Pacific/Saipan
EAT     +03:00  Africa/Addis_Ababa,Africa/Asmara,Africa/Asmera,Africa/Dar_es_Salaam,Africa/Djibouti,Africa/Kampala,Africa/Mogadishu,Africa/Nairobi,Indian/Antananarivo,Indian/Comoro,Indian/Mayotte
EDT     -04:00  America/Detroit,America/Fort_Wayne,America/Grand_Turk,America/Indiana/Indianapolis,America/Indiana/Marengo,America/Indiana/Petersburg,America/Indiana/Vevay,America/Indiana/Vincennes,America/Indiana/Winamac,America/Indianapolis,America/Iqaluit,America/Kentucky/Louisville,America/Kentucky/Monticello,America/Louisville,America/Montreal,America/Nassau,America/New_York,America/Nipigon,America/Pangnirtung,America/Port-au-Prince,America/Thunder_Bay,America/Toronto,Canada/Eastern,EST5EDT,US/East-Indiana,US/Eastern,US/Michigan
EEST    +03:00  Asia/Amman,Asia/Beirut,Asia/Damascus,Asia/Famagusta,Asia/Gaza,Asia/Hebron,Asia/Nicosia,EET,Europe/Athens,Europe/Bucharest,Europe/Chisinau,Europe/Helsinki,Europe/Kiev,Europe/Mariehamn,Europe/Nicosia,Europe/Riga,Europe/Sofia,Europe/Tallinn,Europe/Uzhgorod,Europe/Vilnius,Europe/Zaporozhye
EET     +02:00  Africa/Cairo,Africa/Tripoli,Asia/Amman,Asia/Beirut,Asia/Damascus,Asia/Famagusta,Asia/Gaza,Asia/Hebron,Asia/Nicosia,EET,Egypt,Europe/Athens,Europe/Bucharest,Europe/Chisinau,Europe/Helsinki,Europe/Kaliningrad,Europe/Kiev,Europe/Mariehamn,Europe/Nicosia,Europe/Riga,Europe/Sofia,Europe/Tallinn,Europe/Uzhgorod,Europe/Vilnius,Europe/Zaporozhye,Libya
EST     -05:00  America/Atikokan,America/Cancun,America/Cayman,America/Coral_Harbour,America/Detroit,America/Fort_Wayne,America/Grand_Turk,America/Indiana/Indianapolis,America/Indiana/Marengo,America/Indiana/Petersburg,America/Indiana/Vevay,America/Indiana/Vincennes,America/Indiana/Winamac,America/Indianapolis,America/Iqaluit,America/Jamaica,America/Kentucky/Louisville,America/Kentucky/Monticello,America/Louisville,America/Montreal,America/Nassau,America/New_York,America/Nipigon,America/Panama,America/Pangnirtung,America/Port-au-Prince,America/Thunder_Bay,America/Toronto,Canada/Eastern,EST,EST5EDT,Jamaica,US/East-Indiana,US/Eastern,US/Michigan
GMT     +00:00  Africa/Abidjan,Africa/Accra,Africa/Bamako,Africa/Banjul,Africa/Bissau,Africa/Conakry,Africa/Dakar,Africa/Lome,Africa/Monrovia,Africa/Nouakchott,Africa/Ouagadougou,Africa/Sao_Tome,Africa/Timbuktu,America/Danmarkshavn,Atlantic/Reykjavik,Atlantic/St_Helena,Eire,Etc/GMT,Etc/GMT+0,Etc/GMT-0,Etc/GMT0,Etc/Greenwich,Europe/Belfast,Europe/Dublin,Europe/Guernsey,Europe/Isle_of_Man,Europe/Jersey,Europe/London,GB,GB-Eire,GMT,GMT+0,GMT-0,GMT0,Greenwich,Iceland
HDT     -09:00  America/Adak,America/Atka,US/Aleutian
HKT     +08:00  Asia/Hong_Kong,Hongkong
HST     -10:00  America/Adak,America/Atka,HST,Pacific/Honolulu,Pacific/Johnston,US/Aleutian,US/Hawaii
IDT     +03:00  Asia/Jerusalem,Asia/Tel_Aviv,Israel
IST     +05:30  Asia/Calcutta,Asia/Kolkata
JST     +09:00  Asia/Tokyo,Japan
KST     +09:00  Asia/Pyongyang,Asia/Seoul,ROK
MDT     -06:00  America/Boise,America/Cambridge_Bay,America/Chihuahua,America/Denver,America/Edmonton,America/Inuvik,America/Mazatlan,America/Ojinaga,America/Shiprock,America/Yellowknife,Canada/Mountain,MST7MDT,Mexico/BajaSur,Navajo,US/Mountain
MEST    +02:00  MET
MET     +01:00  MET
MSK     +03:00  Europe/Moscow,Europe/Simferopol,Europe/Tiraspol,W-SU
MST     -07:00  America/Boise,America/Cambridge_Bay,America/Chihuahua,America/Creston,America/Dawson,America/Dawson_Creek,America/Denver,America/Edmonton,America/Fort_Nelson,America/Hermosillo,America/Inuvik,America/Mazatlan,America/Ojinaga,America/Phoenix,America/Shiprock,America/Whitehorse,America/Yellowknife,Canada/Mountain,Canada/Yukon,MST,MST7MDT,Mexico/BajaSur,Navajo,US/Arizona,US/Mountain
NDT     -02:30  America/St_Johns,Canada/Newfoundland
NST     -03:30  America/St_Johns,Canada/Newfoundland
NZDT    +13:00  Antarctica/McMurdo,Antarctica/South_Pole,NZ,Pacific/Auckland
NZST    +12:00  Antarctica/McMurdo,Antarctica/South_Pole,NZ,Pacific/Auckland
PDT     -07:00  America/Ensenada,America/Los_Angeles,America/Santa_Isabel,America/Tijuana,America/Vancouver,Canada/Pacific,Mexico/BajaNorte,PST8PDT,US/Pacific
PKT     +05:00  Asia/Karachi
PST     -08:00  America/Ensenada,America/Los_Angeles,America/Santa_Isabel,America/Tijuana,America/Vancouver,Canada/Pacific,Mexico/BajaNorte,PST8PDT,US/Pacific
SAST    +02:00  Africa/Johannesburg,Africa/Maseru,Africa/Mbabane
SST     -11:00  Pacific/Pago_Pago,Pacific/Samoa,US/Samoa
UTC     +00:00  Etc/UCT,Etc/UTC,Etc/Universal,Etc/Zulu,UCT,UTC,Universal,Zulu
WAT     +01:00  Africa/Bangui,Africa/Brazzaville,Africa/Douala,Africa/Kinshasa,Africa/Lagos,Africa/Libreville,Africa/Luanda,Africa/Malabo,Africa/Ndjamena,Africa/Niamey,Africa/Porto-Novo
WEST    +01:00  Atlantic/Canary,Atlantic/Faeroe,Atlantic/Faroe,Atlantic/Madeira,Europe/Lisbon,Portugal,WET
WET     +00:00  Atlantic/Canary,Atlantic/Faeroe,Atlantic/Faroe,Atlantic/Madeira,Europe/Lisbon,Portugal,WET
WIB     +07:00  Asia/Jakarta,Asia/Pontianak
WIT     +09:00  Asia/Jayapura
WITA    +08:00  Asia/Makassar,Asia/Ujung_Pandang

您可以在 awk 脚本中读取该工具的输出,该脚本需要这些映射来填充tzmap[]我在上面的 awk 脚本中使用的数组,而不是手动填充它。

答案2

我能够实现这一点的唯一方法是使用 GNU date,这涉及大量的重新格式化、为每个新行调用外部可执行文件并将其返回到 awk。

GNU date 可以从文件中读取日期:

% cat foo.dates
2020-12-03T12:23:34 UTC
2020-12-03T12:23:34 Z
2020-12-03T12:23:34 EST
2020-12-03T12:23:34 EDT
2020-12-03T12:23:34 BST
2020-12-03T12:23:34 IST
2020-12-03T12:23:34 +00:00
2020-12-03T12:23:34 -0400
2020-12-03T12:23:34 -0800
2020-12-03T12:23:34 +06:00

% date --file foo.dates +%s
1606998214
1606998214
1607016214
1607012614
1606994614
1606978414
1606998214
1607012614
1607027014
1606976614

即使没有,这似乎是 的工作xargs,而不是 awk 的工作:

% xargs < foo.dates -n 1 -d '\n' date +%s -d
1606998214
1606998214
1607016214
1607012614
1606994614
1606978414
1606998214
1607012614
1607027014
1606976614

相关内容