2014/05/06

UNIX時刻⇔DateTime文字列 変換

UNIX時刻⇔DateTime文字列の変換をガジェットっぽくしてみた。
ついでにGPSの閏秒計算するようにしてみた。
なんというか、検算用にツールにしとこうかなと思いまして。

GPS時刻は、GPS衛星の時計が打ち上がったとき(1980-01-06)の時計らしく
閏秒の補正が途中からされてない状態らしい。
# 閏秒についてちょっと難しくて実はよくわかってないのですけど。
# なんしか、原子時計とUTCはずれてくるから
# いままで合計25回(2015/06/30入れて26回)、6月末か12月末に23:59:60という時間を挿入して調整しているらしい。

挿入した閏秒
1972 0630235960
1972 1231235960
1973 1231235960
1974 1231235960
1975 1231235960
1976 1231235960
1977 1231235960
1978 1231235960
1979 1231235960
----ここからGPS時計スタート----
1981 0630235960
1982 0630235960
1983 0630235960
1985 0630235960
1987 1231235960
1989 1231235960
1990 1231235960
1992 0630235960
1993 0630235960
1994 0630235960
1995 1231235960
1997 0630235960
1998 1231235960
2005 1231235960
2008 1231235960
2012 0630235960
2015 0630235960 add

GPSの時計は、1980-01-06から始まっているから、
今(2014-05)まで打ち上がってから16回調整してない状態になっているんだね。
今は、UTC時刻+16秒=GPS時刻ということ。16秒進んでる。
いちおう過去の時刻も大丈夫、例えば1990-01-01なら6秒とか。

ソースはここにあります。

<できること>

  • 入力したUNIXEpoch[s]をDateTime文字列に変換します
  • 入力したDateTime文字列をUNIXEpoch[s]に変換します(format固定で(^^;))
  • 入力した時間についてGPS時刻で表示します

それでガジェットっぽく貼ってみた。右サイド→
[レイアウト]>[ガジェットを追加]>[HTML/JavaScript]に埋め込んでるだけ。


  • Leap seconds:
    • 入力した時刻のGPS閏秒つまり1980-01-06から調整した閏秒の総和
  • GPS Time:
    • DateTime+Leap seconds
  • Week Number(1980/1/6からの何番目の週か)
    • wn=Math.floor((epogps - 315964800) / 86400 / 7)
  • Time of week(日曜日の0時からの秒)
    • tow=(epogps - 315964800) - (wn * 7 * 86400)
epogpsは入力した時刻+Leap secondsです。
ちなみに、Week Numberは、1024までで表すから、カッコ内は、mod 1024です。

こんなイメージなのですが。
あと、いまから未来に閏秒調整があったら、リスト修正しないとダメですm(_ _)m。

参考したサイト
http://www.enri.go.jp/~sakai/pro.htm

2014/05/05

mongodbで新しいドキュメント取得

やりたいこと
あるコレクションから、
まだ取得していなくて、
新しく追加されたドキュメントを取得したい


例えば、oidが、あるOIDまで取得している状態で、
db.test.find({_id:{$gt:ObjectId(OID)}}).sort({_id:-1});
db.test.find({_id:{$gt:ObjectId(OID)}}).sort({$natural:-1});
などが思い当たりますよね。

ここでOIDは、4つに分けて
536700f5 80bedc 359f 275bc9
the seconds since the Unix epochとmachine identifierとprocess idとcounter
http://docs.mongodb.org/manual/reference/object-id/
らしいから、

これだと秒まで同じドキュメントが複数あって、それらが違うmachine idの場合に対応できないよね。

oidの2つ目のmachine idって

mongo localhost/test1 insert.js
536700f5 80bedc 359f 275bc9

mongo 127.0.0.1/test2 insert.js
536701af dc8c4c 3ebe 80a615

mongoシェルからやったら
53670229 daa151 cae9 41c342

みたいに
同じマシンでもinsertの仕方によっても違うし。

つまり、oidでsortしてもね。

ということで、1秒以内に書き込まれることを考慮したら、
.find({_id:{$gt:ObjectId(OID)}}).sort({_id:-1})では最新を取得できないよね?と思うのですよ。

ということでやっぱり自前のミリ秒くらいまでの時刻フィールド{ts : new Date()}を追加してそれで、
.find({ts:{$gt:timestamp}}).sort({ts:-1})
かつ取ってきたドキュメントでまた持ってないOIDだけに制限して使うことにするわ。


もっといいやり方ないんかね。