UnixTimeの計算

マイコンで 2013/9/16 13:43:33 みたいなのを保存するにはやっぱりUNIXTime。
UNIXTimeは1970年1月1日0:0:0から何秒経ったのかで今の時間を表現するもの。
例えば1971年1月1日0:0:0は 60*60*24*365秒で、これを計算した31536000がUnix時間で表したこの時ってことです。
普通はこの値は32bitのsigned longに保存されるので、2038年ぐらいにいっぱいになっちゃうという問題があります。
まぁあと20年ぐらいは使えるので、ちょっとした物を作るにはこれで十分ですね。32bitに入っちゃうのは魅力。

今回はこれの計算の仕方です。
つまり、1970/1/1からある時刻まで何秒経ったのかを調べる方法です。

厄介なのがうるう年と1ヶ月の長さが30日だったり31日だったりするところです。
フェアフィールドの公式というのがあるのでそれを使います。
[objc]
unsigned int year = 2013;

unsigned int month = 9;
unsigned int day = 16;
unsigned int hour = 0;
unsigned int minute = 0;
unsigned int second = 0;

if(month<3){
month+=12;
year–;
}
#define kEpocDays 719163
#define kSecondsInDay 86400
unsigned int countBy4 = year/4;
unsigned int countBy400 = year/400;
unsigned int countBy100 = year/100;
unsigned int shiftedDay = (306 * (month + 1)) / 10;
unsigned long dayCount = (365 * year + countBy4 – countBy100 + countBy400 + shiftedDay + day – 428) – kEpocDays;
unsigned long UNIX_TIME = dayCount * kSecondsInDay + (hour * 3600) + (minute * 60) + second;
printf("%lu", UNIX_TIME);
[/objc]

この方式の意味はググって下さい。とはいえさらっと紹介すると

前半はうるう年の計算です。ルールとしては
・4で割り切れる年はうるう年
・ただし100で割り切れるならうるう年じゃない
・でも、400で割り切れたらやっぱりうるう年
という感じ。

後半は月と日付から1/1から何日経ったかの計算。
日付は2月だけ例外的に28か29日で他は30か31日になっています。なので、この式の賢いところとしては
1,2月を13,14月としてみなすことです。
つまり、2013年1月は 2012年13月としてこの式に代入して計算します。
すると、2月が一番最後になるのでそれまでの3月から13月は30と31日が交互になって一発で計算できます。

これで、西暦1年1/1からの経過日数が分かります。
あとは、1970年1/1から何時間なのかに変換すればUnixTimeです。
このプログラムの日数計算の部分だけを使い、1969年13月1日0:0:0をいれて1970年1月1日0:0:0までの経過日数を得ます。すると、719163日。

あとは日数計算からこの日付を引いた日数を出し、日時秒を考慮すればUnixTimeです。