UTC时间转其他时区时间
以下代码可以完成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;
}