在 C 中将时间从 UTC 更改为本地时间

Change time from UTC to local time in C

我想在本地时间输出,America/Los_Angeles到日志文件。目前,我正在使用 UTC 时间。我希望这三个函数中存在一个解决方案。

/* src/lib/timing.c line 196 */
char* xdebug_nanotime_to_chars(uint64_t nanotime, unsigned char precision)
{
        char *res;
        time_t secs;

        secs = (time_t)(nanotime / NANOS_IN_SEC);
        if (precision > 0) {
                res = xdmalloc(30);
        } else {
                res = xdmalloc(20);
        }
        strftime(res, 20, "%Y-%m-%d %H:%M:%S", gmtime(&secs));
        if (precision > 0) {
                sprintf(res + 19, ".%09u", (uint32_t)(nanotime % NANOS_IN_SEC));
                if (precision < 9) {
                        *(res + 20 + precision) = '[=10=]';
                }
        }
        return res;
}

打开日志。使用 xdebug_nanotime_to_chars 函数设置 log_open_timestring

/* src/lib/log.c line 586 */
void xdebug_open_log(void)
{
        /* initialize remote log file */
        XG_LIB(log_file) = NULL;
        XG_LIB(log_opened_message_sent) = 0;
        XG_LIB(log_open_timestring) = NULL;

        if (XINI_LIB(log) && strlen(XINI_LIB(log))) {
                XG_LIB(log_file) = xdebug_fopen(XINI_LIB(log), "a", NULL, NULL);
        }
        if (XG_LIB(log_file)) {
                XG_LIB(log_open_timestring) = xdebug_nanotime_to_chars(xdebug_get_nanotime(), 6);
        } else if (strlen(XINI_LIB(log))) {
                xdebug_log_diagnose_permissions(XLOG_CHAN_LOGFILE, NULL, XINI_LIB(log));
        }
}

将日志打开时间打印到日志文件:

/* src/lib/log.c line 56 */
static inline void xdebug_internal_log(int channel, int log_level, const char *message)
{
        zend_ulong pid;

        if (!XG_LIB(log_file)) {
                return;
        }

        pid = xdebug_get_pid();

        if (!XG_LIB(log_opened_message_sent) && XG_LIB(log_open_timestring)) {
                XG_LIB(log_opened_message_sent) = 1;

                fprintf(XG_LIB(log_file), "[" ZEND_ULONG_FMT "] Log opened at %s\n", pid, XG_LIB(log_open_timestring));
                fflush(XG_LIB(log_file));
                xdfree(XG_LIB(log_open_timestring));
                XG_LIB(log_open_timestring) = NULL;
        }

        fprintf(
                XG_LIB(log_file),
                "[" ZEND_ULONG_FMT "] %s%s%s\n",
                pid,
                xdebug_channel_name[channel],
                xdebug_log_prefix[log_level],
                message
        );

        fflush(XG_LIB(log_file));
}

这最终变得非常简单。

我所要做的就是将 gmtime 更改为 localtime,现在所有输出都使用我的系统时间而不是 UTC。

(当然,还必须从我修改过的源代码编译 Xdebug。)

/* src/lib/timing.c line 196 */
char* xdebug_nanotime_to_chars(uint64_t nanotime, unsigned char precision)
{
        char *res;
        time_t secs;

        secs = (time_t)(nanotime / NANOS_IN_SEC);
        if (precision > 0) {
                res = xdmalloc(30);
        } else {
                res = xdmalloc(20);
        }
        /* strftime(res, 20, "%Y-%m-%d %H:%M:%S", gmtime(&secs)); */ right here!
        strftime(res, 20, "%Y-%m-%d %H:%M:%S", localtime(&secs));
        if (precision > 0) {
                sprintf(res + 19, ".%09u", (uint32_t)(nanotime % NANOS_IN_SEC));
                if (precision < 9) {
                        *(res + 20 + precision) = '[=10=]';
                }
        }
        return res;
}

输出现在匹配我当前的时区,即下午 5 点之前:

[12122] Log opened at 2020-12-31 16:50:29.447626
[12122] Log closed at 2020-12-31 16:50:29.780099

我想我可以将时区标识符添加到该行的末尾,如果我想让它绝对清楚的话。如果我这样做,我会编辑我的答案。

编辑:我添加了时区标识符。我创建了一个新函数用于日志打开和关闭函数。

/* src/lib/log.c */
const char* custom_get_tz() /* placed near top of file */
{
        time_t t = time(NULL);
        struct tm lt = {0};
        localtime_r(&t, &lt);
        return lt.tm_zone;
}
.
.
.
 /* around line 63 */
static inline void xdebug_internal_log(int channel, int log_level, const char *message)
{
.
.
.
    /* fprintf(XG_LIB(log_file), "[" ZEND_ULONG_FMT "] Log opened at %s\n", pid, XG_LIB(log_open_timestring)); */
    fprintf(XG_LIB(log_file), "[" ZEND_ULONG_FMT "] Log opened at %s %s\n", pid, XG_LIB(log_open_timestring), custom_get_tz());
.
.
.
}
.
.
.
/* around line 610 */
void xdebug_close_log()
{
.
.
.
    /* fprintf(XG_LIB(log_file), "[" ZEND_ULONG_FMT "] Log closed at %s\n\n", pid, timestr); */
    fprintf(XG_LIB(log_file), "[" ZEND_ULONG_FMT "] Log closed at %s %s\n\n", pid, timestr, custom_get_tz());
.
.
.
}

通过将系统时区更改为 America/Goose_Bay 和 UTC:

进行测试
[31250] Log opened at 2021-01-02 13:44:07.952185 PST
.
.
.
[31250] Log closed at 2021-01-02 13:44:07.957961 PST

[31252] Log opened at 2021-01-02 17:45:55.684079 AST
.
.
.
[31252] Log closed at 2021-01-02 17:45:55.687655 AST

[31254] Log opened at 2021-01-02 21:47:18.788958 UTC
.
.
.
[31254] Log closed at 2021-01-02 21:47:18.792282 UTC