GMT / UTC in hours / minutes of a given time zone without daylight saving time (DST)

I already saw some questions / answers related to this question for other programming languages ​​or operating systems, but I did not find a general solution for my specific scenario. I want to get the GMT offset of a given time zone (regular identifier such as EDT, CET or Europe / Berlin) in a Linux shell script or in pure C.

One simple solution:

$ TZ=":Europe/Berlin" date +%z

But this will print the current GMT offset (including DST if currently in use).

Here is the best example to show what I mean:

$ TZ=":Europe/Berlin" date +%z --date="1 Jan 2014"
+0100

$ TZ=":Europe/Berlin" date +%z --date="1 May 2014"
+0200

I need an option to always get a value other than DST (here: +0100) for any country / city.

Other issues that may solve my problem and are related to this:

-DST (Etc/GMT-1) (/) ?

, DST ?

$ TZ=":Europe/Berlin" date --date="2014-01-01"
Wed Jan  1 00:00:00 CET 2014

$ TZ=":Europe/Berlin" date --date="2014-05-01"
Thu May  1 00:00:00 CEST 2014

CEST ( ) CET ( ), , , - DST = 1 DST = 0 , - . zdump isdst = 0 isdst = 1 , DST, IMO.

+4
2

DST- GMT :

zdump -v "Europe/Berlin" | \
sed ":a;N;\$!ba;s/^.*$(echo -n $(date +%Y)) [^ ]* isdst=0 \
gmtoff=\([^\n]*\)\n.*$/\1/"

3600

, , sed -dst , zdump , zdump , GMT .

+ HHMM -HHMM:

offsetArray=($(zdump -v "America/New_York" | \
sed ":a;N;\$!ba;s/^.*$(echo -n $(date +%Y)) [^ ]* isdst=0 \
gmtoff=\(-*\)\([^\n]*\)\n.*$/\1+ \2/"))
echo "${offsetArray[0]:0:1}$(date -ud @${offsetArray[1]} +%H%M)"

-0500

, . , (1 - 1970 00:00:00 UTC/GMT). Bash , "+" "- +", ( + -).

, , , zdump, , DST, GMT, , , , , 1901 - .

( , , .)

+1

, , 1 , :

TZ=":${city}" date +%z --date="$(date +%Y --date="${date}")-01-01"

:

$ cat t.sh
#!/bin/bash

get_current_modifier()
{
    echo $(TZ=":$1" date +%z --date="$2" 2>/dev/null)
}

get_non_dst_modifier()
{
    echo $(TZ=":$1" date +%z --date="$(date +%Y --date="$2")-01-01" 2>/dev/null)
}

is_dst()
{
    local city=$1
    local date=$2
    local offset1=$(get_non_dst_modifier "${city}" "${date}")
    local offset2=$(get_current_modifier "${city}" "${date}")

    if [ -z "${offset1}" ] || [ -z "${offset2}" ]; then
        return 2
    fi
    [ "${offset1}" != "${offset2}" ]
}

today=$(date +%Y-%m-%d)
printf "%-15s  %-10s  %-5s  %-8s  %-8s\n" CITY DATE 'DST?' 'current' 'non-DST'
while read -r city date; do
    [ -n "${city}" ] || continue
    is_dst "${city}" "${date}"
    case $? in
        0) is_dst=true  ;;
        1) is_dst=false ;;
        2) is_dst=error ;;
    esac
    cur_mod=$(get_current_modifier "${city}" "${date}")
    non_dst=$(get_non_dst_modifier "${city}" "${date}")
    printf "%-15s  %-10s  %-5s  %-8s  %-8s\n" "${city}" "${date}" "${is_dst}" "${cur_mod}" "${non_dst}"
done <<EOT
Europe/Berlin $today
Europe/Berlin 2014-01-01
US/Alaska     $today
US/Alaska     2014-01-01
Europe/Moscow $today
Europe/Moscow 2014-01-01
EOT

.

$ ./t.sh
CITY             DATE        DST?   current   non-DST
Europe/Berlin    2014-05-04  true   +0200     +0100
Europe/Berlin    2014-01-01  false  +0100     +0100
US/Alaska        2014-05-04  true   -0800     -0900
US/Alaska        2014-01-01  false  -0900     -0900
Europe/Moscow    2014-05-04  false  +0400     +0400
Europe/Moscow    2014-01-01  false  +0400     +0400
+1

Source: https://habr.com/ru/post/1537497/


All Articles