1
1

More than 3 years have passed since last update.

指定時刻のエポック秒を得る方法(moment.jsとshell/gdate)

Last updated at Posted at 2020-07-26

目的

  • 時刻や日時の計算は一度エポック秒に変換して加算、減算するのがもっとも間違いが少ないです。

  • そのためJavaScriptでも指定時刻からエポック秒を得たいことがJavaScriptでもShell(Bash)でもあります。サマータイムとか閏とか手動で設定するのは悪夢です。オリジナルコマンドなんか作るのはやめた方がいいです(この考えに行き着くまで苦い経験を繰り返しました)。

  • JavaScriptのデフォルトのDateで格闘するのも否定しませんが、時間かけずにさっさとコーディングしたいものです。

  • JavaScriptにはmoment.jsを導入することにしています。cgiではbash/gdateを使っています

  • moment.jsgdateは互換の無い記述なのでその備忘録としての書いておきます。

  • 検索性が悪かったので全面書き換えしました[2020-09-06]

環境

  • macOS
  • moment.js 2.17
  • bash 5.0.17
  • date (GNU coreutils) 8.32

リンク

JavaScriptでエポック秒と指定フォーマット日時の相互変換

moment.jsの準備

  • JavaScriptのmoment.jsライブラリを使います。<script src="..."></script>なんかでCDNで読めばいいと思います。
  • moment.jsはデフォルトではローカル時間で解析および表示されます。
<!-- moment.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/locale/ja.js"></script>

JavaScript(moment.js)で現在時間と現在のエポック秒の取得

// 現在の時間の取得(ここで出力は省略)
> moment()
// 現在のエポック秒の取得
moment.unix()
< 1595722136

時刻→エポック秒(moment.js)

// 第1引数で指定した時刻のフォーマットは第2引数で指定します。
> moment("200101 123456", "YYMMSS HHmmss").unix()
< 1577849696

エポック秒→時刻( moment.js)

// エポック秒から指定フォーマットに戻します。
> moment.unix(1577849696).format("YYMMDD HHmmss")
< "200101 123456"

// もちろん可読性の高いフォーマットにできます。
> moment.unix(1577849696).format("YYYY-MM-DD HH:mm:ss Z")
< "2020-01-01 12:34:56 +09:00"

moment.jsの時刻のフォーマット(使うものだけ)

  • moment()の時刻表現は非常にフレキシブルなのですが、shellのgdateと表現は似ていて違います。なので忘れます。
  • 私は使うのは下記に限っています。

表1 moment.jsのフォーマット(ここのリンクから改変)

Input Example Description
YY 14 2 digit year
MM 1..12 Month number
HH 0..23 Hours (24 hour time)
mm 0..59 Minutes
ss 0..59 Seconds
Z +12:00 Offset from UTC as +-HH:mm
ZZ +0900 Offset from UTC as +-HHmm
  • 使用例;
    • moment("200101 123456", "YYMMSS HHmmss").unix()
    • moment.unix(1577849696).format("YYMMDD HHmmss")

エポック秒⇄時刻の相互変換(bash)

  • cgi側でも同じことをしたいですね。
  • 実はbashの方が面倒です。

Bashで日時文字列をエポックに変換する

gdateを使う(インストール)

時刻(UNIX形式)→エポック秒(bash)

gdate -d "2020-01-01 12:34:56" +%s
1577849696
# こちらでもOK
gdate -d '2020/01/01 12:34:56' +%s
1577849696
  • エポック秒を得る定番ですね。
  • gdateは入力フォーマットと出力フォーマットを別個に指定できないのでUNIX時間フォーマットで指定する必要があります。
  • 時間指定にはUNIX形式の指定が必要ですが柔軟性を持たせたいですね。

時刻→エポック秒(awkのmktimeを使う)

echo "200101 123456" | fold  -s -w2 |tr '\n' ' ' |awk '{print mktime(20$0)}'
1577849696
# こっちが簡単かな
echo "200101 123456" | fold  -s -w2 |xargs|awk '{print mktime(20$0)}'
1577849696 
  • 少しだけ解説:
  • 文字列200101 123456をfold -s -w2でスペースを気にしないで二文字に分けます。
  • それをtr '\n' ' 'で改行をスペースに分けて、awkのmktime()でエポック秒に変換します。mktime()で必要な最初の項目はは4桁年なので20を$0に加えています。
  • 最初、awkで200101を2020-01-01とかに変換すればいいかと考えましたがawkにはmktime()があるからそれ使えばいいじゃんと考え直した次第です。

時刻→エポック秒(utconvを使う)

cd /usr/local/bin
# インストールします
wget https://gist.githubusercontent.com/richmikan/8703117/raw/e44e6a357cb7423c1a1e58df96da9792c43e80aa/utconv
# 実行権を与えてください
chmod +x utconv
echo "20200101123456" | utconv
1577849696
  • この文字列生成はshellでは比較的簡単でしょう。

エポック秒→時刻(gdate)

  • gdateではエポック秒は@数字で指定します。
gdate '-d @1577849696'
水  1  1 12:34:56 JST 2020
# 可読性の高いフォーマットに
gdate '-d @1577849696' +"%Y-%m-%d %H:%M:%S (%Z)%:z" 
2020-01-01 12:34:56 (JST)+09:00

指定したのは2020年01月01日12:34:56でしたので、正しく戻っています。ローカル時間帯の(JST)で戻っていますね。

表2 GNU dateのフォーマット(ここのリンクから改変)

Input Example Description
%y 00..99 last two digits of year
%m 01..12 month
%d e.g., 01 day of month
%H 00..23 hour
%M 00..59 minute
%S 00..60 second
%z e.g., -0400 +hhmm numeric time zone
%:z e.g., -04:00 +hh:mm numeric time zone
  • 使用例
    • gdate '+%y%m%d %H%M%S'で200726 095643を得ます

エポック秒→時刻(convert -rを使う)

  • 逆の計算もできます。ただしYYMMDDHHmmssです。これからsed/awkなどで色々なフォーマットにできますね。
echo "1577849696" | utconv -r
20200101123456

エポック秒→時刻(awkを使う)

echo "1577849696" | awk '{print strftime("%Y-%m-%d,%H:%M:%S",$0)}'
2020-01-01,12:34:56
  • 自分の備忘録のために書きましたがどなたかのお役に立てれば嬉しいです。
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1