以下代码可以完成UTC时间转其他时区时间,考虑闰年情况,不考虑夏令时情况。时区范围为中时区以西至西十二区,中时区以东至东十四区。
凛冽寒冬,光脚码字,瑟瑟发抖。如有错误,欢迎指出;如有转载,烦请注明。
#include <stdio.h> #include <string.h> typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; #define DAYS_PER_WEEK (7) #define FALSE_DEF (0) #define TRUE_DEF (1) #define BIG_MONTH (1) /**< 大月份,1、3、5、7、8、10、12月 */ #define LITTLE_MONTH (2) /**< 小月份,4、6、9、11月 */ #define FEB_MONTH (3) /**< 二月份 */ typedef struct { uint32_t year; uint8_t month; uint8_t date; uint8_t hour; uint8_t minute; uint8_t second; uint8_t week; }TimeStructure; int32_t isLeapYear(uint32_t year) { if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) { return TRUE_DEF; } else { return FALSE_DEF; } } /** * @brief UTC时间转其他时区时间 * * @param utc_time UTC时间 * @param zone_time 其他时区时间 * @param time_zone 时区,如东八区为8,西5.5区为-5.5。 * @return TRUE_DEF 转换成功 * @return FALSE_DEF 转换失败 */ int32_t UTCTimeToZoneTime(const TimeStructure *utc_time, TimeStructure *zone_time, double time_zone) { int32_t leap_year_flag = FALSE_DEF; /**< 记录UTC时间下的当前年份是否闰年,是为TRUE_DEF,否为FALSE_DEF */ int8_t now_month_size = 0; /**< 记录UTC时间下的当前月份是大月份(一个月有31天)、小月份(一个月有30天)还是二月份 */ uint8_t new_week = 0; int8_t day_changed = 0; /**< 用于记录转换时间涉及日期变更与否,为0表示不变更,为-1便是日期减少一天,为1表示日期增加一天 */ int32_t hour_tmp = 0; int32_t minute_tmp = 0; /* 参数合理性检查 */ if (NULL == utc_time || NULL == zone_time) { printf('\r\n parameter is error! \r\n'); return FALSE_DEF; } /* 时区正确性检查,范围为西十二区至东十四区 */ if (time_zone > 14 || time_zone < -12) { printf('\r\t time zone is error! \r\n'); return FALSE_DEF; } /* 时间格式正确性检查 */ if ((utc_time->month > 12) || (utc_time->date > 31) || (utc_time->hour > 23) || (utc_time->minute > 59) || (utc_time->second > 59) || (utc_time->week > 8) ) { printf('\r\n utc time is error! \r\n'); return FALSE_DEF; } /* 时间格式正确性检查 */ if ((1 == utc_time->month) || (3 == utc_time->month) || (5 == utc_time->month) || (7 == utc_time->month) || (8 == utc_time->month) || (10 == utc_time->month) || (12 == utc_time->month) ) { /* 大月份 */ now_month_size = BIG_MONTH; } else if ((4 == utc_time->month) || (6 == utc_time->month) || (9 == utc_time->month) || (11 == utc_time->month) ) { /* 小月份 */ now_month_size = LITTLE_MONTH; if (utc_time->date > 30) { printf('\r\n utc time is error! \r\n'); return FALSE_DEF; } } else if (2 == utc_time->month) { /* 二月份 */ now_month_size = FEB_MONTH; /* 判断当前年份是否闰年 */ leap_year_flag = isLeapYear(utc_time->year); if (TRUE_DEF == leap_year_flag) { if (utc_time->date > 29) { printf('\r\n utc time is error! \r\n'); return FALSE_DEF; } } else { if (utc_time->date > 28) { printf('\r\n utc time is error! \r\n'); return FALSE_DEF; } } } else { return FALSE_DEF; } /* 用0表示周日,用1~6表示周一至周六 */ if (DAYS_PER_WEEK == utc_time->week) { new_week = 0; } else { new_week = utc_time->week; } //时间换算 hour_tmp = utc_time->hour + (int32_t)time_zone; minute_tmp = utc_time->minute + (int)(time_zone * 10) % 10 * 60 / 10; if (minute_tmp > 59) { hour_tmp += 1; minute_tmp -= 60; } else if (minute_tmp < 0) { hour_tmp -= 1; minute_tmp += 60; } if (hour_tmp > 23) { day_changed = 1; hour_tmp -= 24; } else if (hour_tmp < 0) { day_changed = -1; hour_tmp += 24; } memcpy(zone_time, utc_time, sizeof(TimeStructure)); /* 日期发生改变 */ if (0 != day_changed) { /* 大月份 */ if (BIG_MONTH == now_month_size) { /* 日期增加,东时区 */ if (0 < day_changed) { /* 月末 */ if (31 == utc_time->date) { zone_time->date = 1; /* 十二月,年末 */ if (12 == utc_time->month) { zone_time->year += 1; zone_time->month = 1; } else { zone_time->month += 1; } } else { zone_time->date += 1; } } /* 日期减少,西时区 */ else { /* 月初 */ if (1 == utc_time->date) { /* 一月份 */ if (1 == utc_time->month) { zone_time->date = 31; zone_time->month = 12; zone_time->year -= 1; } /* 三月份 */ else if (3 == utc_time->month) { zone_time->month = 2; /* 三月份要考虑闰年问题 */ if (TRUE_DEF == leap_year_flag) { zone_time->date = 29; } else { zone_time->date = 28; } } /* 八月份 */ else if (8 == utc_time->month) { zone_time->date = 31; zone_time->month -= 1; } /* 其他月份 */ else { zone_time->date = 30; zone_time->month -= 1; } } else { zone_time->date -= 1; } } } /* 小月份 */ else if (LITTLE_MONTH == now_month_size) { /* 日期增加,东时区 */ if (0 < day_changed) { /* 月末 */ if (30 == utc_time->date) { zone_time->date = 1; zone_time->month += 1; } else { zone_time->date += 1; } } /* 日期减少,西时区 */ else { /* 月初 */ if (1 == utc_time->date) { zone_time->date = 31; zone_time->month -= 1; } else { zone_time->date -= 1; } } } /* 二月份 */ else if (FEB_MONTH == now_month_size) { /* 日期增加,东时区 */ if (0 < day_changed) { /* 月末 */ if ((TRUE_DEF == leap_year_flag && 29 == utc_time->date) || (FALSE_DEF == leap_year_flag && 28 == utc_time->date)) { zone_time->date = 1; zone_time->month += 1; } /* 非月末 */ else { zone_time->date += 1; } } /* 日期减少,西时区 */ else { /* 月初 */ if (1 == utc_time->date) { zone_time->date = 31; zone_time->month -= 1; } else { zone_time->date -= 1; } } } else { return FALSE_DEF; } /* 星期的调整 */ zone_time->week = (new_week + DAYS_PER_WEEK + day_changed ) % DAYS_PER_WEEK; } else { /* 日期没有发生改变 */ /* do nothing */ } zone_time->hour = hour_tmp; zone_time->minute = minute_tmp; return TRUE_DEF; } int32_t main(void) { TimeStructure utc_time = { .year = 2020, .month = 12, .date = 5, .hour = 21, .minute = 30 , .second = 00, .week = 6 }; TimeStructure zone_time = {0}; double time_zone = 8; if ( TRUE_DEF == UTCTimeToZoneTime(&utc_time, &zone_time, time_zone)) { printf('\r\n %d-%d-%d %d:%d:%d week: %d\r\n', zone_time.year, zone_time.month, zone_time.date, zone_time.hour, zone_time.minute, zone_time.second, zone_time.week ); } else { printf('\r\n failed! \r\n'); } return 0; }
联系客服