You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Windows C++环境中获取POSIX格式时区字符串?

Windows C++ 生成ONVIF所需POSIX格式时区字符串实现思路

核心思路拆解

POSIX时区格式为STDoffsetDST,start-rule,end-rule(无夏令时则为STDoffset),需从Windows的TIME_ZONE_INFORMATION数据中提取并转换对应字段,分四步实现:

1. 提取并转换时区缩写

TIME_ZONE_INFORMATION返回的StandardName和DaylightName是时区全名(如Pacific Standard Time),需转换为POSIX要求的缩写(如PST):

  • 维护一个常用时区全名与缩写的映射表(比如std::unordered_map<std::wstring, std::string>),覆盖ONVIF设备常见时区;
  • 若遇到冷门时区,可尝试截取全名的首字母组合(如Central Standard Time取CST),或允许用户手动配置补充。

2. 计算UTC偏移值

POSIX格式中的offset是UTC与本地标准时间的小时差(UTC = 本地标准时间 + offset),需从TIME_ZONE_INFORMATION的偏移字段转换:

  • 标准时总偏移:standard_total_bias = tzInfo.Bias + tzInfo.StandardBias(单位:分钟);
  • 转换为小时:standard_offset = standard_total_bias / 60;
  • 夏令时偏移同理:daylight_offset = (tzInfo.Bias + tzInfo.DaylightBias) / 60;
  • 注意符号:若本地时间比UTC早(如UTC+1),offset为负数,需保留符号(如CET-1CEST)。

3. 生成夏令时切换规则

POSIX规则格式为Mm.w.d/hh,对应TIME_ZONE_INFORMATION的DaylightDate(夏令时开始)和StandardDate(夏令时结束):

  • m:SYSTEMTIME.wMonth(1-12);
  • w:SYSTEMTIME.wDay(1=当月第1周,5=当月最后一周);
  • d:SYSTEMTIME.wDayOfWeek(0=周日,1=周一…6=周六);
  • hh:SYSTEMTIME.wHour(24小时制切换时间);
  • 示例:若夏令时在3月第2个周日2点开始,规则为M3.2.0/2。

4. 拼接最终POSIX字符串

  • 有夏令时:标准缩写 + 标准偏移 + 夏令时缩写 + "," + 开始规则 + "," + 结束规则(如PST8PDT,M3.2.0/2,M11.1.0/2);
  • 无夏令时:仅保留标准缩写 + 标准偏移(如EST5)。

代码片段示例

#include <windows.h>
#include <unordered_map>
#include <string>
#include <cstdio>

// 时区全名到缩写的映射表
const std::unordered_map<std::wstring, std::string> TZ_NAME_MAP = {
    {L"Pacific Standard Time", "PST"},
    {L"Pacific Daylight Time", "PDT"},
    {L"Eastern Standard Time", "EST"},
    {L"Eastern Daylight Time", "EDT"},
    // 补充更多常用时区...
};

// 生成POSIX格式的切换规则
std::string generateRule(const SYSTEMTIME& st) {
    // 仅处理每年重复的规则(wYear=0),固定年份规则需额外处理
    if (st.wYear != 0) {
        return "";
    }
    char buf[32];
    sprintf(buf, "M%d.%d.%d/%d", st.wMonth, st.wDay, st.wDayOfWeek, st.wHour);
    return buf;
}

std::string getPosixTimeZone() {
    TIME_ZONE_INFORMATION tzInfo;
    DWORD result = GetTimeZoneInformation(&tzInfo);
    if (result == TIME_ZONE_ID_INVALID) {
        return "";
    }

    // 获取时区缩写
    std::string stdAbbr = TZ_NAME_MAP.at(tzInfo.StandardName);
    std::string dstAbbr = "";
    if (result == TIME_ZONE_ID_DAYLIGHT) {
        dstAbbr = TZ_NAME_MAP.at(tzInfo.DaylightName);
    }

    // 计算UTC偏移(小时)
    int stdOffset = (tzInfo.Bias + tzInfo.StandardBias) / 60;
    int dstOffset = (tzInfo.Bias + tzInfo.DaylightBias) / 60;

    // 拼接结果
    std::string posixTz = stdAbbr + std::to_string(stdOffset);
    if (!dstAbbr.empty()) {
        std::string startRule = generateRule(tzInfo.DaylightDate);
        std::string endRule = generateRule(tzInfo.StandardDate);
        posixTz += dstAbbr + "," + startRule + "," + endRule;
    }

    return posixTz;
}

注意事项

  • 映射表需覆盖目标ONVIF设备支持的时区,避免缩写不匹配;
  • 若GetTimeZoneInformation返回TIME_ZONE_ID_UNKNOWN,说明当前时区无夏令时,需跳过夏令时相关字段;
  • 验证生成的字符串格式,确保符合ONVIF SetSystemDateAndTime API的要求。

内容的提问来源于stack exchange,提问作者Ranjith Ram

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:15:55