Edited at

Objective-CのSQLiteでUNIX timeを扱う

More than 3 years have passed since last update.


UNIX timeとは

1970-01-01T00:00:00Zからの形式的な経過秒数。


別名

UNIX時間、UNIX時刻、POSIX time、Epoch time


問題点


方針


  • SQLite側はUTCで扱う。

  • iOS側はローカルタイムで扱う。(端末設定に従う)

  • 海外対応。

  • 超昔や超未来には対応しない。


    • 2038年問題も基本的に気にしない。




Objective-C


NSDate

//UNIX timeからNSDateを取得

+ (instancetype)dateWithTimeIntervalSince1970:(NSTimeInterval)secs;
//NSDateをUNIX timeで初期化
- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)secs;
//NSDateからUNIX timeを取得
@property (readonly) NSTimeInterval timeIntervalSince1970;

使用例

NSTimeInterval now = NSDate.date.timeIntervalSince1970;

NSLog(@"now = %f", now);
NSDate *date = [NSDate dateWithTimeIntervalSince1970:now];
NSLog(@"NSDate = %@", date);
NSLog(@"UNIXtime = %f", date.timeIntervalSince1970);

//now = 1444186520.342127
//NSDate = 2015-10-07 02:55:20 +0000
//UNIXtime = 1444186520.342127


NSDateFormatter

(まとめ中)


SQLite


Date And Time Functions

http://www.sqlite.org/lang_datefunc.html



  • modifierには'unixepoch'を使う。


  • formatには%sを使う。

sqlite> select datetime( 0, 'unixepoch' ); -- 1970-01-01 00:00:00

sqlite> select strftime( '%Y%m%dT%H%M%SZ', 0, 'unixepoch' ); -- 19700101T000000Z
sqlite> select strftime( '%s', '19700101T000000Z' ); -- NULL /* 基本形式はダメらしい */
sqlite> select strftime( '%s', '1970-01-01T00:00:00Z' ); -- 0

sqlite> select strftime( '%s', 'now' ); -- 1442565125
sqlite> select datetime( 1442565125, 'unixepoch' ); -- 2015-09-18 08:32:05
sqlite> select strftime( '%Y%m%dT%H%M%SZ', 1442565125, 'unixepoch' ); -- 20150918T083205Z
sqlite> select strftime( '%s', '20150918T083205Z' ); -- NULL /* やっぱり基本形式はダメらしい */
sqlite> select strftime( '%s', '2015-09-18T08:32:05Z' ); -- 1442565125


使用例


  • ひと月分のレコード抽出

DATEカラムの型はINTEGERでUNIX timeが入っている。


TESTテーブルからDATEカラムが2015年9月のレコードを抽出する

sqlite> select * from TEST where strftime('%Y%m',DATE,'unixepoch') = '201509';



TESTテーブルからDATEカラムが今月のレコードを抽出する

sqlite> select * from TEST where date(DATE,'unixepoch','start of month') = date('now','start of month');


と書いてはみたものの、日本で「2015年9月」や「今月」と言っても、UTCでは月を跨いでしまうので、このままでは使えない‥。


付録



  • UTC / Wikipedia


  • ISO 8601 / Wikipedia

  • RFC 3339


    • ISO 8601とほぼ同じ?




あとがき

より良い書き方などがあれば教えていただけるとありがたいです。(特にSQLiteはド素人なので)