时间时区服务

更新时间:2025-12-30 06:14:41下载pdf

概述

本文档介绍 TuyaOS SDK 时间时区服务的核心功能、API 及使用方法,适用于需要时间显示、定时任务、时间转换等功能的智能设备开发。

基本概念

时区(Time Zone)

  • 定义:为了统一全球时间管理,国际会议将地球表面按经线从东到西划分成 24 个区域(时区),相邻时区时间相差 1 小时。

  • 核心规则

    • 同一时区内,东西两端看到日出时间差不超过 1 小时。
    • 向东跨越时区,时间增加(东加)。
    • 向西跨越时区,时间减少(西减)。
    • 跨越 N 个时区,时间相应加减 N 小时。
  • 时间标准

    标准 全称 中文名称 说明
    GMT Greenwich Mean Time 格林威治标准时间 传统的零时区时间标准
    UTC Universal Time Coordinated 协调世界时 1972 年后引入,现代科技领域广泛使用

    GMT 和 UTC 在日常使用中可视为相同(都代表零时区时间),但 UTC 是更精确的现代标准。

  • 时区示意图

    时间时区服务

夏令时(Daylight Saving Time, DST)

  • 定义:为节约能源而人为调整时间的制度,也称 日光节约时制夏时制

  • 实施原理

    • 在夏季天亮较早的时期,人为将时间调快 1 小时。
    • 促使人们早睡早起,减少照明用电。
    • 充分利用自然光照资源。
  • 实施情况

    • 全球约 110 个国家 实行夏令时制度。
    • 各国具体实施时间和规则不同。
    • 需要根据当地政策自动切换。
  • 典型时间调整

    • 标准时间 → 夏令时:时钟拨快 1 小时(例:02:00 → 03:00)。
    • 夏令时 → 标准时间:时钟拨慢 1 小时(例:03:00 → 02:00)。

    TuyaOS SDK 会自动处理夏令时切换,开发者无需手动干预。

本地定时(Local Timer)

  • 定义:将定时任务下载到设备本地执行的机制,设备自主检查定时任务是否到期。

  • 核心规则

    • 离线可用:设备离线状态下仍可执行已下载的定时任务。
    • 高可靠性:无需依赖网络连接,定时任务执行更稳定。
    • 低延迟:本地判断,触发响应快速。
  • 工作流程

    • 设备在线时由 App 面板下发定时任务。
    • 定时任务存储到设备本地持久化存储。
    • 设备基于本地时间(含时区和夏令时)周期性检查任务。
    • 到达触发时间点时自动执行对应操作。
    • 任务执行结果可在联网后上报云端。

工作原理

设备App云端启动查询定时任务的定时器增加/删除/修改定时任务下发更新的定时任务回复成功opt[预约定时指令(指令类型 SCHEDULE_SET)]检查是否到了执行定时任务的时间由应用执行对应动作alt[定时任务时间-到了]loop设备App云端

具体指令类型,请参考 复杂协议控制

本地定时依赖于准确的本地时间,请确保设备时间已与云端同步后再使用定时功能。

功能与实现

核心能力

时间时区服务为设备提供完整的时间管理能力:

  • 时区管理:配网后自动从云端获取时区信息,根据手机经纬度智能设置。
  • 夏令时支持:自动识别当地政策,到达切换时间点自动调整。
  • 时间同步:每次与云端交互时自动校准,满足以下条件触发同步:
    • 设备时间慢于服务器时间。
    • 设备时间快于服务器时间 5 秒以上。
    • 设备首次上电校时。
  • 多种格式:支持 UTC 时间、本地时间、日期、秒级/毫秒级时间戳。
  • 时间转换:提供日期与时间戳的双向转换。

应用场景

  • 时间显示:获取本地时间用于 UI 显示。
  • 定时任务:基于准确时间执行定时操作。
  • 时间转换:在不同时间格式之间互相转换。

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);

参数说明

  • tm:POSIX 时间结构指针,包含年月日时分秒等字段。

返回值

  • 返回对应的 UTC 时间戳(秒级)。

时间戳转日期

/**
* @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);

参数说明:

  • tm:UTC 时间戳指针(秒级)。
  • result:输出的 POSIX 时间结构指针,用于存储转换结果。

返回值:

  • 返回 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);

参数说明:

  • tm:输出参数,存储当前系统 UTC 时间的日期时间结构。

返回值:

  • OPRT_OK:成功。
  • 其他:失败,参考 tuya_error_code.h

获取时间戳(秒)

/**
* @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);

返回值:返回当前系统 UTC 时间戳(毫秒级)。

获取系统运行时间

/**
* @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);

参数说明:

  • pSecTime:输出参数,系统运行时间(秒部分)。
  • pMsTime:输出参数,系统运行时间(毫秒部分)。

检查时间同步状态

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

返回值:

  • OPRT_OK:时间已与云端同步。
  • 其他:时间未同步。

获取本地时间

自动适配时区和夏令时规则。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);

参数说明:

  • in_time:需要转换的 UTC 时间戳。若为 0,则获取当前本地时间;否则将该时间戳转换为本地时间。
  • tm:输出参数,存储转换后的本地时间结构(已考虑时区和夏令时)。

返回值:

  • OPRT_OK:成功。
  • 其他:失败,参考 tuya_error_code.h

使用示例

示例一:获取本地时间

OPERATE_RET example_get_local_time(VOID)
{
    POSIX_TM_S tm;
    memset(&tm, 0, SIZEOF(tm));

    // 获取当前本地时间(已考虑时区和夏令时)
    OPERATE_RET ret = tal_time_get_local_time_custom(0, &tm);
    if (OPRT_OK != ret) {
        PR_ERR("get local time failed: %d", ret);
        return ret;
    }

    PR_DEBUG("Local time: %04d-%02d-%02d %02d:%02d:%02d",
            tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
            tm.tm_hour, tm.tm_min, tm.tm_sec);

    return OPRT_OK;
}

示例二:获取高精度时间戳

OPERATE_RET example_get_timestamp(VOID)
{
    // 获取秒级时间戳
    TIME_T sec = tal_time_get_posix();
    PR_DEBUG("UTC timestamp (sec): %u", sec);

    // 获取毫秒级时间戳
    SYS_TICK_T ms = tal_time_get_posix_ms();
    PR_DEBUG("UTC timestamp (ms): %llu", ms);

    // 分离秒和毫秒部分
    TIME_T sec_part = (TIME_T)(ms / 1000);
    UINT_T ms_part = (UINT_T)(ms % 1000);
    PR_DEBUG("Separated: %u.%03u seconds", sec_part, ms_part);

    return OPRT_OK;
}

示例三:时间格式转换

OPERATE_RET example_time_conversion(VOID)
{
    POSIX_TM_S tm;
    TIME_T timestamp;

    // 1. 设置一个日期时间:2025-12-24 10:30:00
    memset(&tm, 0, SIZEOF(tm));
    tm.tm_year = 2025 - 1900;  // 年份从 1900 开始
    tm.tm_mon = 12 - 1;         // 月份从 0 开始(0-11)
    tm.tm_mday = 24;
    tm.tm_hour = 10;
    tm.tm_min = 30;
    tm.tm_sec = 0;

    // 2. 日期转时间戳
    timestamp = tal_time_mktime(&tm);
    PR_DEBUG("Date to timestamp: %u", timestamp);

    // 3. 时间戳转日期
    POSIX_TM_S result;
    tal_time_gmtime_r(&timestamp, &result);
    PR_DEBUG("Timestamp to date: %04d-%02d-%02d %02d:%02d:%02d",
            result.tm_year + 1900, result.tm_mon + 1, result.tm_mday,
            result.tm_hour, result.tm_min, result.tm_sec);

    return OPRT_OK;
}

示例四:检查时间同步状态

OPERATE_RET example_check_sync_status(VOID)
{
    OPERATE_RET ret = tal_time_check_time_sync();
    
    if (OPRT_OK == ret) {
        PR_DEBUG("Time synchronized with cloud server");
        
        // 时间已同步,可以执行依赖时间的操作
        POSIX_TM_S tm;
        tal_time_get_local_time_custom(0, &tm);
        PR_DEBUG("Current local time: %02d:%02d:%02d",
                tm.tm_hour, tm.tm_min, tm.tm_sec);
    } else {
        PR_DEBUG("Time not synchronized yet, please wait...");
        // 可以注册回调或延迟执行依赖时间的操作
    }

    return ret;
}