-
Notifications
You must be signed in to change notification settings - Fork 0
bcddatetime
このライブラリは BCD関連の構造体と関連関数、MJD変換関数を提供する。 7セグメントLEDや、外部RTC(カレンダー)の年月日レジスタ制御、アラーム設定に使用できる。 型変換では地域時差を加減しない。 整数乗除算を使用する。
修正ユリウス通日(MJD)の元期は グレゴリオ暦 1858-11-17 正子 に置く。 これは天文学や宇宙航法などで使われる、長い日数を加減算するのに便利な単位である。
MJD-BCD-UNIX Epoch の関係性は以下の通り。
MJD 0 == BCD 1858-11-17 MJD 元期
MJD 15020 == BCD 1900-01-01 20世紀元旦
MJD 40587 == BCD 1970-01-01 == Epoch 0x0 UNIX Epoch 元期
MJD 51544 == BCD 2000-01-01 == Epoch 0x386D4380 (+10957 day) 21世紀元旦
MJD 65442 == BCD 2038-01-19 == Epoch 0x7FFFD280 (+24855 day) Epoch 31bit幅上限到達日
MJD 65535 == BCD 2038-04-22 == Epoch 0x8079EF70 (+24948 day) MJD 16bit幅表現上限到達日
MJD 90297 == BCD 2106-02-07 == Epoch 0xFFFFA500 (+49710 day) Epoch 32bit幅上限到達日
MJD 106122 == BCD 2149-06-06 (+65535 day) Epoch 相対日数16bit幅上限
MJD 161116 == BCD 2299-12-31 23世紀大晦日
MJD 2973483 == BCD 9999-12-31 西暦4桁BCD上限
(MJD=0x2D5F2B なので22bit範囲)
UNIX Epoch の元期は 1970-01-01 00:00:00 に置くが、自由に再解釈して構わない。(地域時として)
MJD にも Y2038問題がありうることに注意
幾つかの関数を除き、曜日桁は解釈も算出もしない。
算出した場合の表現は0:日(Sun)
〜6:土(Sat)
とする。
グレゴリウス歴の定義から、いわゆる万年カレンダーは400年周期で ちょうど年月日〜曜日対応の関係性が循環する。
400年 × 365日 + 閏日97日 == 146097日 == 20871週 × 7日(端数なし)
この性質から年を下位2桁しか保持できないカレンダーICでも曜日が保持できるなら、 400年範囲内の特定の西暦上位2桁を推測して(センチュリービット機能がなくても)求めることが出来る。
例えば 20世紀元旦 1900-01-01 から 23世紀大晦日 2299-12-31 まで等
(Still alive the YAMATO)
これについては [XRTC_PCF85063A リファレンス] が詳しい。
カレンダーICを12時間表現設定とした場合、
20時台に位置するビット(0x20)が0=午前
:1=午後
を表すようになり
0
時は12
時と表される。
従って24時間表現との相互対応は次のようになる。
24h | 0x00 | 0x01-0x11 | 0x12 | 0x13-0x23 |
---|---|---|---|---|
12h | 0x12 | 0x01-0x11 | 0x32 | 0x21-0x31 |
23:00:00 <-> 31:00:00 (11:00:00 p.m.) (30:59:59の次)
00:00:00 <-> 12:00:00 (12:00:00 a.m.) (31:59:59の次)
01:00:00 <-> 01:00:00 (01:00:00 a.m.) (12:59:59の次)
--
11:00:00 <-> 11:00:00 (11:00:00 a.m.) (10:59:59の次)
12:00:00 <-> 32:00:00 (12:00:00 p.m.) (11:59:59の次)
13:00:00 <-> 21:00:00 (01:00:00 p.m.) (32:59:59の次)
依存性: <inttypes.h>
<stddef.h>
定義される関数はすべて標準C関数(グローバル名前空間)である。
Epoch型の型宣言。単位は秒。主に UNIX Epoch を格納する。
time_t X = 951782400; // 2000-02-29 00:00:00
他の先行するヘッダで定義されているならそれが優先される。 (
signed long
等価の場合がありうる)
MJD日付型の型宣言。単位は日。 主に修正ユリウス通日(MJD)を格納する。
date_t X = 51603; // 2000-02-29
8桁のパックドBCDによる時刻型の型宣言。(予約2桁:時2桁:分2桁:秒2桁)
最上位2桁は予約領域で普通無視されるが、
日数(非BCD 0-255)や曜日(0-7)を保持することが出来る。
bcdtime_t X = 0x03012345;
8桁のパックドBCDによる日付型の型宣言。(年4桁-月2桁-日2桁)
年2桁しか保持できないカレンダーICでは、最上位2桁に0x20
を補うのが普通。
bcddate_t X = 0x20221220;
カレンダーICにセンチュリービット機能がある場合は
0x19
か0x21
を補う。
BCD時刻型 と BCD日付型 の構造体宣言。(リトルエンディアン)
bcddatetime_t X = {0x03012345, 0x20221220};
bcddate_t _date = X.date;
bcdtime_t _time = X.time;
size_t
時刻型 と date_t
日付型 の構造体宣言。(リトルエンディアン)
datetime_t X = {0x012345, 51890};
time_t _time = X.time; // 0x012345
date_t _date = X.date; // 51890
右辺左辺両方で使える型変換支援。ワード型の各桁を読み書きする。(リトルエンディアン)
uint16_t X;
_WB(X)->word = 0x1234;
uint8_t A = _WB(X)->bytes[0]; // 0x34
uint8_t B = _WB(X)->bytes[1]; // 0x12
右辺左辺両方で使える型変換支援。bcddatetime_t
型の各桁を読み書きする。
bcddatetime_t X; // = {0x03012345, 0x20221220};
_BCDDT(X)->bcd.time = 0x03012345; // == _BCDDT(X)->dwords[0]
_BCDDT(X)->bcd.date = 0x20221220; // == _BCDDT(X)->dwords[1]
uint8_t second = _BCDDT(X)->col.second; // 0x45 == _BCDDT(X)->bytes[0]
uint8_t minute = _BCDDT(X)->col.minute; // 0x23 == _BCDDT(X)->bytes[1]
uint8_t hour = _BCDDT(X)->col.hour; // 0x01 == _BCDDT(X)->bytes[2]
uint8_t wday = _BCDDT(X)->col.wday; // 0x03 == _BCDDT(X)->bytes[3]
uint8_t day = _BCDDT(X)->col.day; // 0x20 == _BCDDT(X)->bytes[4]
uint8_t month = _BCDDT(X)->col.month; // 0x12 == _BCDDT(X)->bytes[5]
uint16_t year = _BCDDT(X)->col.year; // 0x2022 == _BCDDT(X)->words[3]
右辺左辺両方で使える型変換支援。bcdtime_t
型の各桁を読み書きする。
bcdtime_t X; // = 0x03012345;
_BCDT(X)->time = 0x03012345; // == _BCDT(X)->dword
uint8_t second = _BCDT(X)->col.second; // 0x45 == _BCDT(X)->bytes[0]
uint8_t minute = _BCDT(X)->col.minute; // 0x23 == _BCDT(X)->bytes[1]
uint8_t hour = _BCDT(X)->col.hour; // 0x01 == _BCDT(X)->bytes[2]
uint8_t wday = _BCDT(X)->col.wday; // 0x03 == _BCDT(X)->bytes[3]
右辺左辺両方で使える型変換支援。bcddate_t
型の各桁を読み書きする。
bcddate_t X; // = 0x20221220;
_BCDD(X)->date = 0x20221220; // == _BCDD(X)->dword
uint8_t day = _BCDD(X)->col.day; // 0x20 == _BCDD(X)->bytes[0]
uint8_t month = _BCDD(X)->col.month; // 0x12 == _BCDD(X)->bytes[1]
uint16_t year = _BCDD(X)->col.year; // 0x2022 == _BCDD(X)->words[1]
整数を2桁のパックドBCDにして返す。
btod
の逆変換。
// 0x23 <- 23
uint8_t Y = dtob(X);
2桁のパックドBCDを整数にして返す。
dtob
の逆変換。
// 23 <- 0x23
uint8_t Y = btob(X);
整数を4桁のパックドBCDにして返す。
wbtod
の逆変換。
// 0x1234 <- 1234
uint16_t Y = wdtob(X);
4桁のパックドBCDを整数にして返す。
wdtob
の逆変換。
// 1234 <- 0x1234
uint16_t Y = wbtod(X);
BCD日付型 と BCD時刻型 から Epoch を求める。
逆変換には
epochToBcdDateTime
あるいは
epochToBcdDate
と
epochToBcdTime
を用いる。
// 951782400 <- 2000-02-29 00:00:00
bcddate_t BCDDATE = 0x20000229;
bcdtime_t BCDTIME = 0x00000000;
time_t EPOCH = bcdToEpoch(DATE, TIME);
BCD日時構造体から Epoch を求める。
epochToBcdDateTime
の逆変換。
// 951782400 <- 2000-02-29 00:00:00
bcddatetime_t BCDDATETIME = {0x000000, 0x20000229};
time_t EPOCH = bcdDateTimeToEpoch(BCDDATETIME);
BCD日時構造体を、24時間表現 から 12時間表現 形式に変換する。
bcdDateTime12to24
の逆変換。
// 2022-12-31 31:59:59 (11:59:59 p.m.) <- 2022-12-31 23:59:59
bcddatetime_t BCDDATETIME = {0x235959, 0x20221231};
bcddatetime_t AMPMDATETIME = bcdDateTime24to12(BCDDATETIME);
12時間表現の BCD日時構造体を、24時間表現 に変換する。
bcdDateTime24to12
の逆変換。
// 2022-12-31 23:59:59 <- 2022-12-31 31:59:59 (11:59:59 p.m.)
bcddatetime_t AMPMDATETIME = {0x315959, 0x20221231};
bcddatetime_t BCDDATETIME = bcdDateTime12to24(AMPMDATETIME);
bcddatetime_t
型からdatetime_t
型を求める。
dateTimeToBcdDateTime
の逆変換。
datetime_t t_dt = bcdDateTimeToDateTime(t_bcd);
BCD日付型 から 修正ユリウス通日(MJD)を求める。
mjdToBcdDate
の逆変換。
// MJD:51603 <- 2000-02-29
bcddate_t BCDDATE = 0x20000229;
date_t MJD = bcdDateToMjd(BCDDATE);
BCD日付型 から 曜日 を求める。表現は0:日(Sun)
〜6:土(Sat)
とする。
// WDAY:2 <- 2000-02-29
bcddate_t BCDDATE = 0x20000229;
uint8_t WDAY = bcdDateToWeekday(BCDDATE);
BCD時刻型 から Epoch を求める。
BCD 00:23:59:59 からは 整数 86399 と求まる。
bcd_time
の最上位2桁は無視される。
epochToBcdDayTime
の逆変換。
// EPOCH:86399 <- 23:59:59
bcdtime_t BCDTIME = 0x235959;
time_t EPOCH = bcdTimeToEpoch(BCDTIME);
BCD時刻型 から Epoch を求める。
BCD 00:23:59:59 からは 整数 86399 と求まる。
最上位2桁は BCD ではなく 1バイト幅整数と見なし、
これを丸めないので 256日未満の通算秒数が得られる。
epochToBcdDayTime
の逆変換。
// EPOCH:172799 <- 1:23:59:59
bcdtime_t BCDTIME = 0x01235959;
time_t EPOCH = bcdTimeToSeconds(BCDTIME);
BCD時刻型を、24時間表現 から 12時間表現 形式に変換する。
bcdTime12to24
の逆変換。
// 31:59:59 (11:59:59 p.m.) <- 23:59:59
bcdtime_t BCDTIME = 0x235959;
bcdtime_t AMPMTIME = bcdTime24to12(BCDTIME);
12時間表現の BCD時刻型を、24時間表現に変換する。
bcdTime24to12
の逆変換。
// 23:59:59 <- 31:59:59 (11:59:59 p.m.)
bcdtime_t AMPMTIME = 0x315959;
bcdtime_t BCDTIME = bcdTime12to24(AMPMTIME);
修正ユリウス通日(MJD)から BCD日付型 を求める。
bcdDateToMjd
の逆変換。
// 2000-02-29 <- MJD:51603
date_t MJD = 51603
bcddate_t BCDDATE = mjdToBcdDate(MJD);
修正ユリウス通日(MJD)から 曜日 を求める。表現は0:日(Sun)
〜6:土(Sat)
とする。
// WDAY:2 <- 2000-02-29 <- MJD:51603
date_t MJD = 51603
uint8_t WDAY = mjdToWeekday(MJD);
修正ユリウス通日(MJD)から Epoch を求める。
時分秒は含まないので結果は 86400 の倍整数になる。
表現範囲は 1970-01-01 から 2106-02-07 未満まで。
epochToMjd
の逆変換。
// EPOCH:951782400 <- 2000-02-29 00:00:00 <- MJD:51603
date_t MJD = 51603
time_t EPOCH = mjdToEpoch(MJD);
datetime_t
型つまりMJD
とEpoch
の組からtime_t
を求める。
epochToDateTime
の逆変換。
Epoch
は86400
進数と見做してその過不足をMJD
項に加減算する。
time_t t_time dateTimeToEpoch((const datetime_t){86400 * -7, 51890});
// t_time = 51883 * 86400;
datetime_t
型からbcddatetime_t
型を求める。
bcdDateTimeToDateTime
の逆変換。
bcddatetime_t t_bcd = dateTimeToBcdDateTime(t_dt);
Epoch から 修正ユリウス通日(MJD)を求める。
mjdToEpoch
の逆変換。
// MJD:51603 <- 2000-02-29 00:00:00 <- EPOCH:951782400
time_t EPOCH = 951782400;
date_t MJD = epochToMjd(EPOCH);
Epoch から BCD日時構造体 を求める。
bcdDateTimeToEpoch
の逆変換。
// 2000-02-29 00:00:00 <- EPOCH:951782400
time_t EPOCH = 951782400;
bcddatetime_t BCDDATETIME = epochToBcdDateTime(EPOCH);
Epoch から BCD日付型 を求める。
逆変換にはbcdToEpoch
を用いる。
// 2000-02-29 <- 2000-02-29 00:00:00 <- EPOCH:951782400
time_t EPOCH = 951782400;
bcddate_t BCDDATE = epochToBcdDate(EPOCH);
Epoch から BCD時刻型 を求める。
逆変換にはbcdToEpoch
を用いる。
// 00:00:00 <- 2000-02-29 00:00:00 <- EPOCH:951782400
time_t EPOCH = 951782400;
bcdtime_t BCDTIME = epochToBcdTime(EPOCH);
Epoch から BCD時刻型 を求めるが、通算日も含める。
bcdTimeToSeconds
の逆変換。
最上位2桁は BCD ではなく1バイト幅の整数。(0-255)
// 1:23:59:59 <- EPOCH:172799
time_t EPOCH = 172799;
bcdtime_t BCDTIME = epochToBcdDayTime(EPOCH);
time_t
型からdatetime_t
型つまりMJD
とEpoch
の組を求める。
dateTimeToEpoch
の逆変換。
datetime_t t_dt = epochToDateTime(7 * 86400 + 1234);
// t_dt = {1234, 7};
Epoch から 曜日 を求める。表現は0:日(Sun)
〜6:土(Sat)
とする。
// WDAY:2 <- 2000-02-29 00:00:00 <- EPOCH:951782400
time_t EPOCH = 951782400;
uint8_t WDAY = epochToWeekday(EPOCH);
Twitter(X): @askn37
BlueSky Social: @multix.jp
GitHub: https://github.com/askn37/
Product: https://askn37.github.io/
Copyright (c) 2022,2023 askn (K.Sato) multix.jp
Released under the MIT license
https://opensource.org/licenses/mit-license.php
https://www.oshwa.org/
multix.jp/てくにかるむ(休眠中)
Multix Zinnia Product SDK [*AVR]
AVR.JP(日本語訳)
AVR-LIBC(日本語訳)