2012年4月22日日曜日

秒から年月日時分秒に

C語で秒から年月日時分秒に変換するコードです
標準関数?
それが無いんだなぁ
(探し方が悪いんだろうけど 自分で作ったほうが早かった というか printfですら無いんだからtimeとか探す気にも(ry)


void S2S(char *buf, int counter) {
    int year = 1970,  month = 1, day = 1, hour = 0, min = 0, sec = 0;

    while(counter >= 31536000) {
        if (((year + 1) % 4 == 0) && ((year + 1) % 100 != 0) || ((year + 1) % 400 == 0)) {
            if (counter < 31622400) { break; }
            counter -= 31622400;
            year++;
        } else {
            counter -= 31536000;
            year++;
        }
    }
   
    while(counter >= 86400) {
    counter -= 86400;
    day++;
    if (month == 1 && day == 32) { day = 1; month++; }
    if (month == 2) {
            if (year%4 == 0 && year%100 != 0 || year%400 == 0) {
            if (day == 30) { day = 1; month++; }
            } else {
                if (day == 29) { day = 1; month++; }
            }
    }
    if (month == 3  && day == 32) { day = 1; month++; }
    if (month == 4  && day == 31) { day = 1; month++; }
    if (month == 5  && day == 32) { day = 1; month++; }
    if (month == 6  && day == 31) { day = 1; month++; }
    if (month == 7  && day == 32) { day = 1; month++; }
    if (month == 8  && day == 32) { day = 1; month++; }
    if (month == 9  && day == 31) { day = 1; month++; }
    if (month == 10 && day == 32) { day = 1; month++; }
    if (month == 11 && day == 31) { day = 1; month++; }
    if (month == 12 && day == 32) { day = 1; month = 1; year++; }
    }
    while(counter >= 3600)
    { counter -= 3600; hour++; }
    while(counter >= 60)
    { counter -=   60; min++; }
    sec = counter;

    sprintf(&buf[0], "%4d/%02d/%02d %02d:%02d:%02d", year, month, day, hour, min, sec);
}

こんな感じです
第二引数で与えられた秒を第一引数で与えられたバッファに挿入
UNIXtimeですが まぁそこはてきとーに書きなおしてください
一応動くはずです
このコードは閏年にも対応しているので 余程のことが無い限りは大丈夫だと思いますが

例のごとく自己責任で使ってください

かるーく動作説明すると
最初にintで変数を宣言します
32ビット環境なら24byte使います
で 最初のwhileで年を処理しますが
ifで閏年か平年かを分けてから処理します
もしも翌年が閏年なのに秒が366日分の秒数に届かなければbreakで抜け出します

その次に日の処理をします
1日分の秒数以上あれば秒を減らして日をインクリメント
もしも月をまたぐようであればその処理も一緒にします
ここはifを多用しているので重いと思います

で そのあとは時間と分の処理
最後に秒に残りを代入してから
sprintfで文字列にします
直接生の値で受け取りたければint宣言をせずに
引数でポインタを受け取って 初期化してから という方法も使えます
というかそのほうが使いやすいと思います
PICとかで使うなら
月日時分秒をcharで作ったほうが大幅にメモリ節約できますが
今回はARMで使う予定だったのでintを使いました

ってことで こんなところです

STBeeでRTCを使う方法も近々うpする予定
(いつになるかはわからないけど)

0 件のコメント:

コメントを投稿