Linux:大陸/都市形式でタイムゾーンを取得する安定した方法

Linux:大陸/都市形式でタイムゾーンを取得する安定した方法

私は、ヨーロッパ/キエフなどの大陸/都市形式でLinuxシステム(主に異なるバージョンのDebian)のタイムゾーンを取得するための移植可能で強力な方法を探しています。

これまでに使用したこのアプローチの問題は、timedatectl status | grep zone | cut -d' ' -f10 Debian 9では動作しますがDebian 10では動作しないことです(ドッカーイメージを使用して簡単に確認できます)。

これを行うより良い、より一般的で移植可能な方法はありますか?それ以外の場合、上記のコマンドをDebian 9と10の両方で機能するようにどのように変更する必要がありますか?

答え1

timedatectl status | awk '/zone/ {print $3}'

答え2

地理的なタイムゾーン名は抽象的で便利です。内部的に、タイムゾーンデータファイルは、オフセット、不連続性、およびDSTの変更を一覧表示しますが、場所はリストしないバイナリファイルです(ファイル名がそれを示していても問題が発生します/etc/localtime)。場所から地図があります。と日付タイムゾーンオフセットに適用されますが、1:1ではありません。たとえば、出力が与えられると、date使用している地理的位置を簡単かつ決定的に導き出すことはできません(ただし、現在の日付に対して互換性のある場所のセットを計算できます。または次のものを使用できます)。少しの努力、場所を推論するために、前の日付に不連続性を確認してください)。

一つある地域名のマスターリストおよびタイムゾーン定義ファイルのように見える:

# Zone  NAME            GMTOFF  RULES   FORMAT  [UNTIL]
Zone    Europe/London   -0:01:15 -      LMT     1847 Dec  1 0:00s
                         0:00   GB-Eire %s      1968 Oct 27
                         1:00   -       BST     1971 Oct 31 2:00u
                         0:00   GB-Eire %s      1996
                         0:00   EU      GMT/BST
Link    Europe/London   Europe/Jersey
Link    Europe/London   Europe/Guernsey
Link    Europe/London   Europe/Isle_of_Man

バイナリが作成されると、表示されたEurope/Londonルールが処理され、一時ルール(変更が発生したタイムスタンプ、比較チェックzdump -v Europe/London)が作成され、関連する場所にエイリアスが割り当てられます。上記のファイルの内容や出力は区別できません localtimedate

抽象化を使用すると、適時に法的変更を処理できます。

# TZ=Europe/Andorra date -d "Aug 31 1984"
Fri Aug 31 00:00:00 CET 1984

TZ=Europe/Andorra date -d "Aug 31 1985"
Sat Aug 31 00:00:00 CEST 1985

(アンドラはEUに属していませんが、1985年からEU DST規則に従いました。)

/etc/localtime(バイナリ)タイムゾーンのデータファイルであり、Debianは通常、指定された地理的タイムゾーンファイルへのシンボリックリンクでなければなりません(次のように)。「緊張」(9) そして「バスター」(10)localtimeマニュアルページ:

/etc/localtime ファイルは、アプリケーションがユーザーに表示するために使用するローカルシステムのシステム全体のタイムゾーンを構成します。 /usr/share /zoneinfo/への絶対または相対シンボリックリンクでなければならず、その後に「Europe / Berlin」や「Etc / UTC」などのタイムゾーン識別子が続く必要があります。生成されたリンクは、構成されたタイムゾーンに対応するバイナリtzfile(5)タイムゾーンデータを指す必要があります。

タイムゾーン識別子は/ etc / localtimeのシンボリックリンクターゲット名から抽出されるため、ファイルは通常のファイルまたはハードリンクではない可能性があります。

次のような場合を考えてみましょう。

if [ -L /etc/localtime ]; then
  IFS=/ read -a TZFILE < <(readlink -f /etc/localtime)
  printf -v TZNAME "%s/%s\n" ${TZFILE[-2]} ${TZFILE[-1]}
  echo $TZNAME
fi

以前のバージョンでは(または誰かが文書に従わなかった場合)コピータイムゾーンデータファイル。だからこれを確認し、/etc/localtimeあなた/etc/timezoneの意見に同意するためにそれらを比較する必要があります:

$ diff -s /etc/localtime /usr/share/zoneinfo/`cat /etc/timezone`
Files /etc/localtime and /usr/share/zoneinfo/America/New_York are identical

戻るまたは基本的に移動する必要がある場合:

read CHECK file < <(sha256sum /etc/localtime)
while read sum file; do 
  [[ "$sum" == "$CHECK" ]] && printf "%s\n" "$file"
done < <(find /usr/share/zoneinfo/ -type f |xargs sha256sum)

これは実際に移植可能な答えではありません(POSIXはこれらの答えを定義または要求しません)。長い名前、ICANN / IANAから来ており、systemdそのバージョンのDebianでコマンドを使用しています。

答え3

/etc/timezoneファイルからタイムゾーンをインポートできます。

cat /etc/timezone

答え4

これはUnixとMacシステムの両方で動作します。

readlink /etc/localtime | awk -F'/' '{print $(NF-1)"/"$(NF)}'

関連情報