在调试蓝牙MCU时间戳功能时,很多主流的UNIX时间戳计算工具就失效了,因为server端需要下发小端的HEX转换结果,因此我写了这个鸡肋工具来辅助调试:
cpp
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include <time.h>
static bool is_leap_year(uint16_t year)
{
return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
}
static uint8_t days_in_month(uint16_t year, uint8_t month)
{
static const uint8_t days[] = {
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};
if (month < 1 || month > 12)
return 0;
if (month == 2 && is_leap_year(year))
return 29;
return days[month - 1];
}
static uint32_t local_time_to_unix_utc(uint16_t year,
uint8_t month,
uint8_t day,
uint8_t hour,
uint8_t min,
uint8_t sec,
int16_t timezone_offset_min)
{
uint32_t days = 0;
for (uint16_t y = 1970; y < year; y++)
days += is_leap_year(y) ? 366 : 365;
for (uint8_t m = 1; m < month; m++)
days += days_in_month(year, m);
days += day - 1;
int64_t local_seconds = (int64_t)days * 86400
+ (int64_t)hour * 3600
+ (int64_t)min * 60
+ sec;
return (uint32_t)(local_seconds - (int64_t)timezone_offset_min * 60);
}
static void build_time_sync_payload(uint16_t year,
uint8_t month,
uint8_t day,
uint8_t hour,
uint8_t min,
uint8_t sec,
int16_t timezone_offset_min,
uint8_t out[6])
{
uint32_t unix_sec = local_time_to_unix_utc(
year, month, day, hour, min, sec, timezone_offset_min
);
out[0] = (uint8_t)(unix_sec);
out[1] = (uint8_t)(unix_sec >> 8);
out[2] = (uint8_t)(unix_sec >> 16);
out[3] = (uint8_t)(unix_sec >> 24);
out[4] = (uint8_t)(timezone_offset_min);
out[5] = (uint8_t)(timezone_offset_min >> 8);
}
int main(void)
{
uint8_t payload[6];
time_t now = time(NULL);
struct tm local_tm;
localtime_s(&local_tm, &now);
build_time_sync_payload(
local_tm.tm_year + 1900, // 年
local_tm.tm_mon + 1, // 月 (0-11 -> 1-12)
local_tm.tm_mday, // 日
local_tm.tm_hour, // 时
local_tm.tm_min, // 分
local_tm.tm_sec, // 秒
480, // 时区偏移(分钟),UTC+8
payload
);
printf("payload hex: ");
for (int i = 0; i < 6; i++)
printf("%02X", payload[i]);
printf("\n");
return 0;
}
可以直接编译成exe放在这边。