[C] 日付関係のユーティリティ ================================================================================ 日付関係のユーティリティとして、次のようなものを作った。 関数の概要 --- time_t toSystemTime(char *dateString); 日付文字列をシステム時刻に変換 time_t toStrictSystemTime(char* dateString); 日付文字列をシステム時刻に変換 char* toDateString(char *dateString, time_t systemTime); システム時刻を日付文字列に変換 char* toJaWeekString(char *weekString, time_t systemTime) システム時刻を曜日(日、月、...、土)文字列に変換 int isLeap(int year); year 年がうるう年か平年かを返す int lastMonthDay(int year, int month); year 年 month 月の最後の日付を返す --- 関数の詳細 --- time_t toSystemTime(char *dateString); 日付文字列をシステム時刻に変換する。 日付は、西暦年が 1901 以上、月は 1~12 の範囲、日は 1~31 の範囲内でなければ不 正な日付とする。 引数 dateString 日付を表す文字列("YYYYMMDD") 戻り値 システム時刻(1970年1月1日 0時0分0秒からの経過時間(秒単位))。変換でき ない場合、-1. time_t toStrictSystemTime(char* dateString); 日付文字列をシステム時刻に変換する。 日付は、西暦年が1901以上とするが、厳密に月・日の範囲内でなければ不正な日付と する。 引数 dateString 日付を表す文字列("YYYYMMDD") 戻り値 システム時刻(1970年1月1日 0時0分0秒からの経過時間(秒単位))。変換でき ない場合、-1. char* toDateString(char *dateString, time_t systemTime); システム時刻を日付文字列に変換する。 引数 systemTime システム時刻 引数 dateString 日付を表す文字列を格納する文字列へのポインター 戻り値 日付を表す文字列("YYYYMMDD") char* toJaWeekString(char *weekString, time_t systemTime) { システム時刻を曜日(日、月、...、土)文字列に変換する。 引数 systemTime システム時刻 引数 weekString 曜日を表す文字列を格納する文字列へのポインター 戻り値 曜日を表す文字列 int isLeap(int year); year年がうるう年か平年かを返す。 引数 year 西暦年。正数を指定する。 戻り値 うるう年のとき1、平年のとき0 int lastMonthDay(int year, int month); year年month月の最後の日付を返す。 引数 year 西暦年 引数 month 月。ただし、通常の月より1引いた値を使う(0~11) 戻り値 year年month月の最後の日付 --- ▲ 公開用ヘッダー □ DateUtil.h --- /* ============================================================================ Name : DateUtil.h Author : marunomaruno Version : V1.0, 2012-06-08 Copyright : marunomaruno Description : 日付を扱うユーティリティ(公開用) ============================================================================ */ #ifndef DATEUTIL_H_ #define DATEUTIL_H_ enum { YEAR_LENGTH = 4, MONTH_LENGTH = 2, DAY_LENGTH = 2, }; /** * システム時刻を曜日(日、月、...、土)文字列に変換する。 * @param systemTime システム時刻 * @param weekString 曜日を表す文字列を格納する文字列へのポインター * @return 曜日を表す文字列 */ char* toJaWeekString(char *weekString, time_t systemTime); /** * year年がうるう年か平年かを返す。 * @param year 西暦年。正数を指定する。 * @return うるう年のとき1、平年のとき0 */ int isLeap(int year); /** * year年month月の最後の日付を返す。 * @param year 西暦年 * @param month 月。ただし、通常の月より1引いた値を使う(0~11) * @return year年month月の最後の日付 */ int lastMonthDay(int year, int month); /** * 日付文字列をシステム時刻に変換する。 * 日付は、西暦年が1900以上とするが、厳密に月・日の範囲内でなければ不正な日付と する。 * @param dateString 日付を表す文字列("YYYYMMDD") * @return システム時刻(1970年1月1日 0時0分0秒からの経過時間(秒単位))。変換でき ない場合、-1. */ time_t toStrictSystemTime(char* dateString); /** * 日付文字列をシステム時刻に変換する。 * 日付は、西暦年が1901以上、月は1~12の範囲、日は1~31の範囲内でなければ不正な日 付とする。 * @param dateString 日付を表す文字列("YYYYMMDD") * @return システム時刻(1970年1月1日 0時0分0秒からの経過時間(秒単位))。変換でき ない場合、-1. */ time_t toSystemTime(char *dateString); /** * システム時刻を日付文字列に変換する。 * @param systemTime システム時刻 * @param dateString 日付を表す文字列を格納する文字列へのポインター * @return 日付を表す文字列("YYYYMMDD") */ char* toDateString(char *dateString, time_t systemTime); #endif /* DATEUTIL_H_ */ ---- ▲ 非公開用ヘッダー 内部的に使うだけの関数の定義。 リトルエンディアンを意識するのはここだけ。 □ DateUtilInner.h --- /* ============================================================================ Name : DateUtilInner.h Author : marunomaruno Version : V1.0, 2012-06-08 Copyright : marunomaruno Description : 日付を扱うユーティリティ(非公開用) ============================================================================ */ #ifndef DATE_UTIL_INNER_H_ #define DATE_UTIL_INNER_H_ static struct tm* makeTMStruct(char* weekString, struct tm* workTime); #endif /* DATE_UTIL_INNER_H_ */ --- ▲ モジュール □ DateUtil.c --- /* ============================================================================ Name : DateUtil.c Author : marunomaruno Version : V1.0, 2012-06-08 Copyright : marunomaruno Description : 日付を扱うユーティリティ ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <assert.h> #include "DateUtil.h" #include "DateUtilInner.h" /** * 日付文字列をシステム時刻に変換する。 * 日付は、西暦年が1900以上とするが、厳密に月・日の範囲内でなければ不正な日付と する。 * @param dateString 日付を表す文字列("YYYYMMDD") * @return システム時刻(1970年1月1日 0時0分0秒からの経過時間(秒単位))。変換でき ない場合、-1. */ time_t toStrictSystemTime(char* dateString) { struct tm workTime; if (strlen(dateString) != (YEAR_LENGTH + MONTH_LENGTH + DAY_LENGTH)) { return -1; } if (makeTMStruct(dateString, &workTime) == NULL) { return -1; } if (workTime.tm_mday > lastMonthDay(workTime.tm_year, workTime.tm_mon)) { return -1; } return (mktime(&workTime)); } /** * 日付文字列をシステム時刻に変換する。 * 日付は、西暦年が1901以上、月は1~12の範囲、日は1~31の範囲内でなければ不正な日 付とする。 * @param dateString 日付を表す文字列("YYYYMMDD") * @return システム時刻(1970年1月1日 0時0分0秒からの経過時間(秒単位))。変換でき ない場合、-1. */ time_t toSystemTime(char* dateString) { struct tm workTime; if (makeTMStruct(dateString, &workTime) == NULL) { return -1; } return (mktime(&workTime)); } struct tm* makeTMStruct(char* weekString, struct tm* workTime) { char year[YEAR_LENGTH + 1]; char month[MONTH_LENGTH + 1]; char day[DAY_LENGTH + 1]; if (strlen(weekString) != (YEAR_LENGTH + MONTH_LENGTH + DAY_LENGTH)) { return NULL; } // 年を設定する strncpy(year, weekString + 0, YEAR_LENGTH); year[YEAR_LENGTH] = '¥0'; workTime->tm_year = atoi(year) - 1900; if (workTime->tm_year <= 0) { return NULL; } // 月を設定する strncpy(month, weekString + (YEAR_LENGTH), MONTH_LENGTH); month[MONTH_LENGTH] = '¥0'; workTime->tm_mon = atoi(month) - 1; if (workTime->tm_mon < 0 || workTime->tm_mon > 11) { return NULL; } // 日を設定する strncpy(day, weekString + (YEAR_LENGTH + MONTH_LENGTH), DAY_LENGTH); day[DAY_LENGTH] = '¥0'; workTime->tm_mday = atoi(day); if (workTime->tm_mday < 1 || workTime->tm_mday > 31) { return NULL; } // 時刻を設定する workTime->tm_hour = 0; workTime->tm_min = 0; workTime->tm_sec = 0; workTime->tm_isdst = -1; return workTime; } /** * システム時刻を日付文字列に変換する。 * @param systemTime システム時刻 * @param dateString 日付を表す文字列を格納する文字列へのポインター * @return 日付を表す文字列("YYYYMMDD") */ char* toDateString(char *dateString, time_t systemTime) { struct tm* time = localtime(&systemTime); strftime(dateString, ((YEAR_LENGTH + MONTH_LENGTH + DAY_LENGTH) + 1), "%Y%m%d", time); return dateString; } /** * システム時刻を曜日(日、月、...、土)文字列に変換する。 * @param systemTime システム時刻 * @param weekString 曜日を表す文字列を格納する文字列へのポインター * @return 曜日を表す文字列 */ char* toJaWeekString(char *weekString, time_t systemTime) { const char WEEK[][3] = { "日", "月", "火", "水", "木", "金", "土", "日", }; struct tm* time = localtime(&systemTime); strncpy(weekString, WEEK[time->tm_wday], 2); weekString[2] = '¥0'; return weekString; } /** * year年がうるう年か平年かを返す。 * @param year 西暦年。正数を指定する。 * @return うるう年のとき1、平年のとき0 */ int isLeap(int year) { assert(year > 0); return (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)); } /** * year年month月の最後の日付を返す。 * @param year 西暦年 * @param month 月。ただし、通常の月より1引いた値を使う(0~11) * @return year年month月の最後の日付 */ int lastMonthDay(int year, int month) { const int LAST_DAYS[][2] = { { 31, 31 }, // 1 { 28, 29 }, // 2 { 31, 31 }, // 3 { 30, 30 }, // 4 { 31, 31 }, // 5 { 30, 30 }, // 6 { 31, 31 }, // 7 { 31, 31 }, // 8 { 30, 30 }, // 9 { 31, 31 }, // 10 { 30, 30 }, // 11 { 31, 31 }, // 12 }; return LAST_DAYS[month][isLeap(year)]; } --- ▲ テスト 上記の関数を確認するためのテスト・プログラム。 数字、ひらがな、かたかなの限界値をチェックする。 また、リトルエンディアン前提なので、バイト順が逆転している場合に範囲になるかどう かもチェックする。 □ DateUtilTest.c --- /* ============================================================================ Name : DateUtilTest.c Author : marunomaruno Version : V1.0, 2012-06-08 Copyright : marunomaruno Description : 日付を扱うユーティリティのテスト ============================================================================ */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <assert.h> #include "DateUtil.h" int main(void) { time_t calendarTime; char buffer[100]; printf("test start¥n"); fflush(stdout); // isLeap() assert(isLeap(2000)); assert(isLeap(2012)); assert(!isLeap(2013)); assert(!isLeap(2100)); // lastMonthDay() assert(31 == lastMonthDay(2012, 0)); assert(29 == lastMonthDay(2012, 1)); assert(31 == lastMonthDay(2012, 2)); assert(30 == lastMonthDay(2012, 3)); assert(31 == lastMonthDay(2012, 4)); assert(30 == lastMonthDay(2012, 5)); assert(31 == lastMonthDay(2012, 6)); assert(31 == lastMonthDay(2012, 7)); assert(30 == lastMonthDay(2012, 8)); assert(31 == lastMonthDay(2012, 9)); assert(30 == lastMonthDay(2012, 10)); assert(31 == lastMonthDay(2012, 11)); assert(31 == lastMonthDay(2013, 0)); assert(28 == lastMonthDay(2013, 1)); assert(31 == lastMonthDay(2013, 2)); assert(30 == lastMonthDay(2013, 3)); assert(31 == lastMonthDay(2013, 4)); assert(30 == lastMonthDay(2013, 5)); assert(31 == lastMonthDay(2013, 6)); assert(31 == lastMonthDay(2013, 7)); assert(30 == lastMonthDay(2013, 8)); assert(31 == lastMonthDay(2013, 9)); assert(30 == lastMonthDay(2013, 10)); assert(31 == lastMonthDay(2013, 11)); // 本日 printf("%s¥n", toDateString(buffer, time(NULL))); printf("%s¥n", toJaWeekString(buffer, time(NULL))); // toCalendarTime(), toStrictCalendarTime(), toDateString(), toJaWeekString () // 1. 平年 strcpy(buffer, "20100228"); calendarTime = toSystemTime(buffer); assert(strcmp("20100228", toDateString(buffer, calendarTime)) == 0); assert(strcmp("日", toJaWeekString(buffer, calendarTime)) == 0); // 2. 平年(厳密にはエラー) strcpy(buffer, "20100229"); calendarTime = toSystemTime(buffer); assert(strcmp("20100301", toDateString(buffer, calendarTime)) == 0); assert(strcmp("月", toJaWeekString(buffer, calendarTime)) == 0); // 3. 平年 strcpy(buffer, "20100228"); calendarTime = toStrictSystemTime(buffer); assert(strcmp("20100228", toDateString(buffer, calendarTime)) == 0); assert(strcmp("日", toJaWeekString(buffer, calendarTime)) == 0); // 4. 平年(エラー) strcpy(buffer, "20100229"); calendarTime = toStrictSystemTime(buffer); assert(calendarTime == -1); // 5. うるう年 strcpy(buffer, "20120229"); calendarTime = toSystemTime(buffer); assert(strcmp("20120229", toDateString(buffer, calendarTime)) == 0); assert(strcmp("水", toJaWeekString(buffer, calendarTime)) == 0); // 6. うるう年(厳密にはエラー) strcpy(buffer, "20120230"); calendarTime = toSystemTime(buffer); assert(strcmp("20120301", toDateString(buffer, calendarTime)) == 0); assert(strcmp("木", toJaWeekString(buffer, calendarTime)) == 0); // 7. うるう年 strcpy(buffer, "20120229"); calendarTime = toStrictSystemTime(buffer); assert(strcmp("20120229", toDateString(buffer, calendarTime)) == 0); assert(strcmp("水", toJaWeekString(buffer, calendarTime)) == 0); // 8. 平うるう年(エラー) strcpy(buffer, "20120230"); calendarTime = toStrictSystemTime(buffer); assert(calendarTime == -1); // 9. 日付不正(1900年) strcpy(buffer, "19000101"); calendarTime = toSystemTime(buffer); assert(calendarTime == -1); calendarTime = toStrictSystemTime(buffer); assert(calendarTime == -1); // 10. 日付不正(0月) strcpy(buffer, "20000010"); calendarTime = toSystemTime(buffer); assert(calendarTime == -1); calendarTime = toStrictSystemTime(buffer); assert(calendarTime == -1); // 11. 日付不正(32日) strcpy(buffer, "20120532"); calendarTime = toSystemTime(buffer); assert(calendarTime == -1); calendarTime = toStrictSystemTime(buffer); assert(calendarTime == -1); // 12. 日付不正(9文字) strcpy(buffer, "201205301"); calendarTime = toSystemTime(buffer); assert(calendarTime == -1); calendarTime = toStrictSystemTime(buffer); assert(calendarTime == -1); // 13. 日付不正(7文字) strcpy(buffer, "2012053"); calendarTime = toSystemTime(buffer); assert(calendarTime == -1); calendarTime = toStrictSystemTime(buffer); assert(calendarTime == -1); printf("test end¥n"); fflush(stdout); return 0; } --- 以上
最新の画像[もっと見る]
-
あけましておめでとうございます 11年前
-
今年もよろしくお願いいたします 12年前
-
あけましておめでとうございます 13年前
-
あけましておめでとうございます 16年前
※コメント投稿者のブログIDはブログ作成者のみに通知されます