时间时区服务

更新时间:2023-12-19 08:36:58下载pdf

本文介绍时间时区服务,有助于您了解基本概念、功能描述、适用场景、工作原理/实现方案和 API。

基本概念

时区

为了照顾到各地区的使用方便,又使其他地方的人容易将本地的时间换算到别的地方时间上去,有关国际会议决定将地球表面按经线从东到西,划成一个个区域,并且规定相邻区域的时间相差 1 小时。在同一区域内的东端和西端的人看到太阳升起的时间最多相差不过 1 小时。当人们跨过一个区域,就将自己的时钟校正 1 小时(向西减 1 小时,向东加 1 小时),跨过几个区域就加或减几小时。

  • GMT 全称 Greenwich Mean Time,中文为格林威治标准时间。
  • UTC 全称 Universal Time Coordinated,中文为协调世界时。

GMT 和 UTC 都是代表零时区的时间,两者相等。UTC 是 1972 年之后引入的概念,是 GMT 的后继,现在广泛应用于科技领域。

时间时区服务

夏令时

夏令时表示为了节约能源,人为规定时间的意思。也叫夏时制,夏令时(Daylight Saving Time,DST),又称 日光节约时制夏令时间,在这一制度实行期间所采用的统一时间称为 夏令时间。一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。

各个采纳夏时制的国家具体规定不同。全世界有近 110 个国家每年要实行夏令时。

功能描述

设备配网激活之后,根据配网手机所在的经纬度,给设备设置时区/夏令时,为设备各种功能提供时间服务,并能够在设备时间不准确的时候自动更新。

适用场景

  • 时间显示:获取本地时间。
  • 时间转换:不同形式之间的时间互相转换。
  • 定时任务:执行夏令时的国家和地区,根据当地政策自动切换夏令时。

工作原理/实现方案

激活

TuyaOS 在设备配网之后,会从云端获取设备所在的时区和夏令时信息。设备将维护这些信息,并给予这些信息提供各种时间服务,例如获取 UTC 时间,获取本地时间,获取日期,同时也提供时间转换等服务。

时间同步

每次设备和云端交互的时候,就会拿到当前服务器的 UTC 时间戳。当设备时间和服务器 UTC 时间满足以下条件,会进行 UTC 时间校准:

  • 当前设备 UTC 时间小于服务器 UTC 时间(时钟变慢了)
  • 当前设备 UTC 时间大于服务器 UTC 时间 5 秒(时间快了 5 秒)
  • 时间未同步过(设备上电后首次校时)

API 说明

日期转时间戳

将日期转换成时间戳。

/**
* @brief change posix time to TIME_T, redefine the std C func mktime
*
* @param[in] tm the time in posix time format
* @return the time in TIME_T format
*/
TIME_T tal_time_mktime(IN CONST POSIX_TM_S *tm);

时间戳转日期

将时间戳转换成日期。

/**
* @brief change TIME_T to posix time, redefine the std C func gmtime_r
*
* @param[in] tm the time in TIME_T format
* @param[out] result the time in posix time format
* @return the time in posix time format
*/
POSIX_TM_S *tal_time_gmtime_r(IN CONST TIME_T *tm, OUT POSIX_TM_S *result);

获取日期时间

获取系统日期,时间为 UTC 时间。

/**
* @brief get TuyaOS UTC time in posix time format
*
* @param[out] tm the IoTOS UTC time in posix time format
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*/
OPERATE_RET tal_time_get(OUT POSIX_TM_S *tm);

获取时间戳-秒级别

获取时间戳,时间戳为 UTC 时间,精度为秒。

/**
* @brief get TuyaOS UTC time in TIME_T format
*
* @return the current second time in TIME_T format
*/
TIME_T tal_time_get_posix(VOID);

获取时间戳-毫秒级别

获取时间戳,时间戳为 UTC 时间,精度为毫秒。

/**
* @brief get TuyaOS UTC time in SYS_TICK_T format
*
* @return the current micro-second time in SYS_TICK_T format
*/
SYS_TICK_T tal_time_get_posix_ms(VOID);

获取系统时间

获取系统运行时间。

/**
* @brief how long times system run
*
* @param[out] pSecTime the current time in second
* @param[out] pMsTime the current time in micro-second
* @return VOID
*/
VOID tal_time_get_system_time(OUT TIME_S *pSecTime,OUT TIME_MS *pMsTime);

检查时间是否同步

检查当前设备时间与云端时间是否同步。如果没有同步,很多依赖于时间的功能都可能不准确。

/**
* @brief check TuyaOS time synchronize status
*
* @return OPRT_OK on synchronized. Others on not
*/
OPERATE_RET tal_time_check_time_sync(VOID);

获取本地时间

获取本地时间,当 in_time0 的时候,获取当前设备的本地时间。当 in_time 不为 0 的时候,将 in_time 转换成本地时间。

计算本地时间的时候,会将时区、夏令时的规则考虑进来,获取的时间是符合设备所在地区的法定时间。

/**
* @brief get TuyaOS local time (local, contains the time zone and summer time zone)
*
* @param[in] in_time the time need translate
* @param[out] tm the local time in posix format
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*
* @note if in_time is 0, return the IoTOS local time, otherwise, translate the in_time to
* local time
*/
OPERATE_RET tal_time_get_local_time_custom(IN TIME_T in_time, OUT POSIX_TM_S *tm);

使用示例

OPERATE_RET sample_delaywork_service_test()
{
    // 获取当前时间
    POSIX_TM_S tm;
    memset(&tm, 0, SIZEOF(tm));

    // 当前本地时间
    tal_time_get_local_time_custom(0, &tm);
    PR_DEBUG("current local time in sec: [%02d-%02d %02d:%02d:%02d]",
                    tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);


    // 当前本地时间毫秒
    SYS_TICK_T time_ms = tal_time_get_posix_ms();
    TIME_T sec = (TIME_T)(time_ms / 1000);
    UINT_T ms  = (UINT_T)(time_ms % 1000);
    tal_time_get_local_time_custom(sec, &tm);
    PR_DEBUG("current local time in ms:[%02d-%02d %02d:%02d:%02d:%d]",tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, ms);

    return OPRT_OK;
}