将日期和时间数字转换为 time_t 并指定时区

2023-12-30

我有以下整数:

int y, mon, d, h, min, s;

他们的价值观是:2012, 06, 27, 12, 47, 53分别。如果我在应用程序中的其他地方选择了“UTC”,我想表示“2012/06/27 12:47:53 UTC”的日期时间,或者如果我在应用程序中的其他地方选择了“2012/06/27 12:47:53 AEST”在我的申请中的其他地方选择了“AEST”。

我想把它转换成time_t,这是我当前使用的代码:

struct tm timeinfo;
timeinfo.tm_year = year - 1900;
timeinfo.tm_mon = mon - 1;
timeinfo.tm_mday = day;
timeinfo.tm_hour = hour;
timeinfo.tm_min = min;
timeinfo.tm_sec = sec;
//timeinfo.tm_isdst = 0; //TODO should this be set?

//TODO find POSIX or C standard way to do covert tm to time_t without in UTC instead of local time
#ifdef UNIX
return timegm(&timeinfo);
#else
return mktime(&timeinfo); //FIXME Still incorrect
#endif

所以我正在使用tm struct and mktime,但是这效果不佳,因为它总是假设我当地的时区。

这样做的正确方法是什么?

以下是我迄今为止提出的解决方案。 它基本上执行以下三件事之一:

  1. 如果是 UNIX,只需使用timegm
  2. If not UNIX
    1. Either, do math using the difference between UTC epoch and local epoch as an offset
      • 保留:数学可能不正确
    2. Or, set the "TZ" environment variable to UTC temporarily
      • 保留:如果/当此代码需要多线程时将会出错
namespace tmUtil
{
    int const tm_yearCorrection = -1900;
    int const tm_monthCorrection = -1;
    int const tm_isdst_dontKnow = -1;

#if !defined(DEBUG_DATETIME_TIMEGM_ENVVARTZ) && !(defined(UNIX) && !defined(DEBUG_DATETIME_TIMEGM))
    static bool isLeap(int year)
    {
        return
            (year % 4) ? false
            : (year % 100) ? true
            : (year % 400) ? false
            : true;
    }

    static int daysIn(int year)
    {
        return isLeap(year) ? 366 : 365;
    }
#endif
}

time_t utc(int year, int mon, int day, int hour, int min, int sec)
{
    struct tm time = {0};
    time.tm_year = year + tmUtil::tm_yearCorrection;
    time.tm_mon = mon + tmUtil::tm_monthCorrection;
    time.tm_mday = day;
    time.tm_hour = hour;
    time.tm_min = min;
    time.tm_sec = sec;
    time.tm_isdst = tmUtil::tm_isdst_dontKnow;

    #if defined(UNIX) && !defined(DEBUG_DATETIME_TIMEGM) //TODO remove && 00
        time_t result;
        result = timegm(&time);
        return result;
    #else
        #if !defined(DEBUG_DATETIME_TIMEGM_ENVVARTZ)
            //TODO check that math is correct
            time_t fromEpochUtc = mktime(&time);

            struct tm localData;
            struct tm utcData;
            struct tm* loc = localtime_r (&fromEpochUtc, &localData);
            struct tm* utc = gmtime_r (&fromEpochUtc, &utcData);
            int utcYear = utc->tm_year - tmUtil::tm_yearCorrection;
            int gmtOff =
                (loc-> tm_sec - utc-> tm_sec)
                + (loc-> tm_min - utc-> tm_min) * 60
                + (loc->tm_hour - utc->tm_hour) * 60 * 60
                + (loc->tm_yday - utc->tm_yday) * 60 * 60 * 24
                + (loc->tm_year - utc->tm_year) * 60 * 60 * 24 * tmUtil::daysIn(utcYear);

            #ifdef UNIX
                if (loc->tm_gmtoff != gmtOff)
                {
                    StringBuilder err("loc->tm_gmtoff=", StringBuilder((int)(loc->tm_gmtoff)), " but gmtOff=", StringBuilder(gmtOff));
                    THROWEXCEPTION(err);
                }
            #endif

            int resultInt = fromEpochUtc + gmtOff;
            time_t result;
            result = (time_t)resultInt;
            return result;
        #else
            //TODO Find a way to do this without manipulating environment variables
            time_t result;
            char *tz;
            tz = getenv("TZ");
            setenv("TZ", "", 1);
            tzset();
            result = mktime(&time);
            if (tz)
                setenv("TZ", tz, 1);
            else
                unsetenv("TZ");
            tzset();
            return result;
        #endif
    #endif
}

N.B. StringBuilder是一个内部类,对于这个问题的目的来说并不重要。

更多信息:

我知道这可以使用 boost 等轻松完成。但这不是选择。我需要以数学方式完成它,或者使用 c 或 c++ 标准函数或其组合。

timegm似乎解决了这个问题,但是,它似乎并不是 C/POSIX 标准的一部分。该代码目前在多个平台(Linux、OSX、WIndows、iOS、Android (NDK))上编译,因此我需要找到一种方法使其在所有这些平台上工作,即使解决方案涉及#ifdef $PLATFORM键入东西。


这让我有点想吐在嘴里,但你可以将它转换为字符串strftime(),替换字符串中的时区,然后将其转换回来strptime()并进入一个time_t with mktime()。详细地:

#ifdef UGLY_HACK_VOIDS_WARRANTY
time_t convert_time(const struct tm* tm)
{
    const size_t BUF_SIZE=256;
    char buffer[BUF_SIZE];
    strftime(buffer,256,"%F %H:%M:%S %z", tm);
    strncpy(&buffer[20], "+0001", 5); // +0001 is the time-zone offset from UTC in hours
    struct tm newtime = {0};
    strptime(buffer, "%F %H:%M:%S %z", &newtime);
    return mktime(&newtime);
}
#endif

然而,我强烈建议你说服权力,毕竟提升是一种选择。 Boost 对自定义时区有很好的支持。还有其他库也可以优雅地做到这一点。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将日期和时间数字转换为 time_t 并指定时区 的相关文章

随机推荐

  • 创建一个调用 jsf 方法的简单链接

    我正在创建一个注销链接 这是注销 bean 的代码 public void doLogout try FacesContext getCurrentInstance getExternalContext getSessionMap put
  • 在“输入”元素之前或之后生成CSS内容[重复]

    这个问题在这里已经有答案了 在 Firefox 3 和 Google Chrome 8 0 中 以下内容按预期工作 span Test span 但当元素为
  • Java 中的套接字和进程

    在Java中 最好的方法是打开一个持续监听的端口 并且在收到数据包时仍然发送 目前我对网络编程还不是特别精通 所以我在网上找到的教程并不是特别有帮助 将侦听套接字作为服务器套接字并在我用来向服务器发送数据的套接字的单独线程中运行它是否有意义
  • 从静态方法访问非静态成员变量

    我刚刚开始学习 Java 需要一些帮助 我知道我无法对静态方法进行非静态引用 但我需要帮助来解决它 我读到您可以通过创建对象的实例来访问非静态成员变量 但我不确定具体如何操作 这是代码中的一些内容 任何帮助或指示将不胜感激 package
  • 根据 xml 元素的值进行流量控制

    我有一个很长的 xml 数据文件 其中包含 500 多个项目 它的形式如下
  • 如何访问HTML5视频解码功能?

    HTML5 有
  • 为什么这个 LINQ 表达式会破坏我的循环和转换逻辑?

    背景 ArticleService是一个类 为前端层提供方法 方便与后端业务 它的两个基本职责是转换 ViewModel ArticleViewModel 到适当的模型 Article 在保存数据时 反之 在获取数据时将模型转换为 View
  • 从 .NET 中的 COM 对象包装器重定向 STDERR 输出

    我正在尝试在 NET 库中使用 ImageMagick COM 对象 ImageMagickObject 该库旨在从 IronRuby 中调用 但这并不是那么重要 我想采用这种方法 因为它适合我现有的调用 当前调用 ImageMagick
  • 带 D3 (v4) 直方图函数的胖尾意味着空箱

    我正在尝试充分利用 D3 直方图函数 但由于笨拙的肥尾数据分布而陷入困境 这data points下面的数组涉及多年来的国家人口密度 像香港这样人口密度高的城市是造成 肥尾 的原因 我想将数据分成八个单独的桶 我没有指定一个域 我假设直方图
  • 如何使用 NHibernate 模式生成更新数据库表模式?

    我试图弄清楚如何使用 NHibernate 配置和映射来更新表模式 而不是删除并重新创建它们 目前我正在使用NHibernate Tool hbm2ddl SchemaExportobj 使用 FluentNHibernate 生成 mys
  • 相当于给定 wget 命令的 Python

    我正在尝试创建一个与 wget 命令执行相同操作的 Python 函数 wget c read timeout 5 tries 0 URL c 如果下载中断 则从上次中断的地方继续 read timeout 5 如果超过 5 秒没有新数据传
  • 如何在React js文本区域内渲染漂亮的json数据?

    我是 React js 新手 我在渲染文本区域内漂亮的 json 数据时遇到问题 我不知道哪一部分是错误的 我希望我的 Prettyjson 像这样在 textarea 内渲染 email email protected cdn cgi l
  • 首先使用代码禁用整数主键上的标识(自动递增)

    我在 ASP NET MVC 3 应用程序中使用代码优先方法 并在模型中使用所有整数主键 public int Id get set 默认情况下配置为自动递增的身份 如何禁用此功能并启用手动输入主键整数的方法 实际情况是Id整数具有特殊的含
  • 如何摆脱这个 Do-While 循环?

    我有这个基本的 Arduino 代码 我想要退出此 Do While 循环的 2 个选项 我简化了原始代码以突出真正的问题 Do While无法识别 OR 退出循环的条件 在此代码中 我从两个等于 0 的整数变量开始 一旦它们进入 Do W
  • Git 推送结果致命:协议错误:错误的行长度字符:这

    我正在尝试让 GitLab 在我的服务器上运行 运行 CentOS 6 5 我跟着gitlab 菜谱 https github com gitlabhq gitlab recipes blob master install centos R
  • 如何创建一个包含纬度和经度的数组,并使用for循环来标记android中谷歌地图上的位置

    我刚刚开始在 android 中编码 经过很长一段时间 我让我的谷歌地图可以工作 并且能够在上面放置标记 接下来我想做的是创建一个 latlng 数组并使用 for 循环在谷歌地图上放置一个标记 我不知道该怎么做 有人可以帮助我吗 到目前为
  • 更改 Windows 中的默认 MySQL 用户

    如果我运行mysql or mysqldump从命令提示符运行程序 我在 Windows 中得到这个 ERROR 1045 28000 Access denied for user ODBC localhost using password
  • 内联三元运算符不起作用

    由于某种原因 我的三元运算符分配不适用于数组的第二部分 有人看到我做错了什么吗 它应该只是查看永久链接字段是否有值 如果没有则插入link url进入数组 function getSiteMap this gt db gt select s
  • Firefox 中的文本描边和阴影 CSS3

    我想知道是否有一种方法可以在文本中添加描边和阴影 我可以让它在 Chrome 和 Safari 中工作 因为 webkit 支持文本描边和文本阴影 我可以在 Firefox 中显示笔划 但那是使用文本阴影并使用偏移量 那么有人知道解决这个问
  • 将日期和时间数字转换为 time_t 并指定时区

    我有以下整数 int y mon d h min s 他们的价值观是 2012 06 27 12 47 53分别 如果我在应用程序中的其他地方选择了 UTC 我想表示 2012 06 27 12 47 53 UTC 的日期时间 或者如果我在