• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

taosdata / TDengine / #5059

17 May 2026 01:15AM UTC coverage: 73.443% (+0.06%) from 73.387%
#5059

push

travis-ci

web-flow
feat (TDgpt): Dynamic Model Synchronization Enhancements (#35344)

* refactor: do some internal refactor.

* fix: fix multiprocess sync issue.

* feat: add dynamic anomaly detection and forecasting services

* fix: log error message for undeploying model in exception handling

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Potential fix for pull request finding

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix: handle undeploy when model exists only on disk

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/286aafa0-c3ce-4c27-b803-2707571e9dc1

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: guard dynamic registry concurrent access

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/5e4db858-6458-40f4-ac28-d1b1b7f97c18

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: tighten service list locking scope

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/5e4db858-6458-40f4-ac28-d1b1b7f97c18

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: restore prophet support and update tests per review feedback

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/92298ae1-7da6-4d07-b20e-101c7cd0b26b

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* fix: improve test name and move copy inside lock scope

Agent-Logs-Url: https://github.com/taosdata/TDengine/sessions/92298ae1-7da6-4d07-b20e-101c7cd0b26b

Co-authored-by: hjxilinx <8252296+hjxilinx@users.noreply.github.com>

* Potential fix for pull request finding

Co-au... (continued)

281870 of 383795 relevant lines covered (73.44%)

135516561.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.44
/source/os/src/osTime.c
1
/*
2
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
3
 *
4
 * This program is free software: you can use, redistribute, and/or modify
5
 * it under the terms of the GNU Affero General Public License, version 3
6
 * or later ("AGPL"), as published by the Free Software Foundation.
7
 *
8
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
 * FITNESS FOR A PARTICULAR PURPOSE.
11
 *
12
 * You should have received a copy of the GNU Affero General Public License
13
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14
 */
15

16
#define ALLOW_FORBID_FUNC
17
#define _BSD_SOURCE
18

19
#ifdef DARWIN
20
#define _XOPEN_SOURCE
21
#else
22
#define _XOPEN_SOURCE 500
23
#endif
24

25
#define _DEFAULT_SOURCE
26

27
#include "os.h"
28
#include "osInt.h"
29

30
#ifdef WINDOWS
31
// Declare timezone variable for Windows (not available in Windows CRT)
32
long timezone = 0;
33
#endif
34

35
#if defined(WINDOWS) || defined(TD_ASTRA)
36

37
#include <stdlib.h>
38
#include <string.h>
39
#include <time.h>
40
// #define TM_YEAR_BASE 1970 //origin
41
#define TM_YEAR_BASE 1900  // slguan
42

43
// This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC)
44
// until 00:00:00 January 1, 1970
45
static const uint64_t TIMEEPOCH = ((uint64_t)116444736000000000ULL);
46

47
/*
48
 * We do not implement alternate representations. However, we always
49
 * check whether a given modifier is allowed for a certain conversion.
50
 */
51
#define ALT_E 0x01
52
#define ALT_O 0x02
53
#define LEGAL_ALT(x)                   \
54
  {                                    \
55
    if (alt_format & ~(x)) return (0); \
56
  }
57

58
static int conv_num(const char **buf, int *dest, int llim, int ulim) {
59
  int result = 0;
60

61
  /* The limit also determines the number of valid digits. */
62
  int rulim = ulim;
63

64
  if (**buf < '0' || **buf > '9') return (0);
65

66
  do {
67
    result *= 10;
68
    result += *(*buf)++ - '0';
69
    rulim /= 10;
70
  } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
71

72
  if (result < llim || result > ulim) return (0);
73

74
  *dest = result;
75
  return (1);
76
}
77

78
static const char *day[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
79
static const char *abday[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
80
static const char *mon[12] = {"January", "February", "March",     "April",   "May",      "June",
81
                              "July",    "August",   "September", "October", "November", "December"};
82
static const char *abmon[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
83
static const char *am_pm[2] = {"AM", "PM"};
84

85
#else
86
#include <sys/time.h>
87
#endif
88

89
char *taosStrpTime(const char *buf, const char *fmt, struct tm *tm) {
2,147,483,647✔
90
  if (!buf || !fmt || !tm) return NULL;
2,147,483,647✔
91
#if defined(WINDOWS) || defined(TD_ASTRA) 
92
  char        c;
93
  const char *bp;
94
  size_t      len = 0;
95
  int         alt_format, i, split_year = 0;
96

97
  bp = buf;
98

99
  while ((c = *fmt) != '\0') {
100
    /* Clear `alternate' modifier prior to new conversion. */
101
    alt_format = 0;
102

103
    /* Eat up white-space. */
104
    if (isspace(c)) {
105
      while (isspace(*bp)) bp++;
106

107
      fmt++;
108
      continue;
109
    }
110

111
    if ((c = *fmt++) != '%') goto literal;
112

113
  again:
114
    switch (c = *fmt++) {
115
      case '%': /* "%%" is converted to "%". */
116
      literal:
117
        if (c != *bp++) return (0);
118
        break;
119

120
        /*
121
         * "Alternative" modifiers. Just set the appropriate flag
122
         * and start over again.
123
         */
124
      case 'E': /* "%E?" alternative conversion modifier. */
125
        LEGAL_ALT(0);
126
        alt_format |= ALT_E;
127
        goto again;
128

129
      case 'O': /* "%O?" alternative conversion modifier. */
130
        LEGAL_ALT(0);
131
        alt_format |= ALT_O;
132
        goto again;
133

134
        /*
135
         * "Complex" conversion rules, implemented through recursion.
136
         */
137
      case 'c': /* Date and time, using the locale's format. */
138
        LEGAL_ALT(ALT_E);
139
        if (!(bp = taosStrpTime(bp, "%x %X", tm))) return (0);
140
        break;
141

142
      case 'D': /* The date as "%m/%d/%y". */
143
        LEGAL_ALT(0);
144
        if (!(bp = taosStrpTime(bp, "%m/%d/%y", tm))) return (0);
145
        break;
146

147
      case 'R': /* The time as "%H:%M". */
148
        LEGAL_ALT(0);
149
        if (!(bp = taosStrpTime(bp, "%H:%M", tm))) return (0);
150
        break;
151

152
      case 'r': /* The time in 12-hour clock representation. */
153
        LEGAL_ALT(0);
154
        if (!(bp = taosStrpTime(bp, "%I:%M:%S %p", tm))) return (0);
155
        break;
156

157
      case 'T': /* The time as "%H:%M:%S". */
158
        LEGAL_ALT(0);
159
        if (!(bp = taosStrpTime(bp, "%H:%M:%S", tm))) return (0);
160
        break;
161

162
      case 'X': /* The time, using the locale's format. */
163
        LEGAL_ALT(ALT_E);
164
        if (!(bp = taosStrpTime(bp, "%H:%M:%S", tm))) return (0);
165
        break;
166

167
      case 'x': /* The date, using the locale's format. */
168
        LEGAL_ALT(ALT_E);
169
        if (!(bp = taosStrpTime(bp, "%m/%d/%y", tm))) return (0);
170
        break;
171

172
        /*
173
         * "Elementary" conversion rules.
174
         */
175
      case 'A': /* The day of week, using the locale's form. */
176
      case 'a':
177
        LEGAL_ALT(0);
178
        for (i = 0; i < 7; i++) {
179
          /* Full name. */
180
          len = strlen(day[i]);
181
          if (strncmp(day[i], bp, len) == 0) break;
182

183
          /* Abbreviated name. */
184
          len = strlen(abday[i]);
185
          if (strncmp(abday[i], bp, len) == 0) break;
186
        }
187

188
        /* Nothing matched. */
189
        if (i == 7) return (0);
190

191
        tm->tm_wday = i;
192
        bp += len;
193
        break;
194

195
      case 'B': /* The month, using the locale's form. */
196
      case 'b':
197
      case 'h':
198
        LEGAL_ALT(0);
199
        for (i = 0; i < 12; i++) {
200
          /* Full name. */
201
          len = strlen(mon[i]);
202
          if (strncmp(mon[i], bp, len) == 0) break;
203

204
          /* Abbreviated name. */
205
          len = strlen(abmon[i]);
206
          if (strncmp(abmon[i], bp, len) == 0) break;
207
        }
208

209
        /* Nothing matched. */
210
        if (i == 12) return (0);
211

212
        tm->tm_mon = i;
213
        bp += len;
214
        break;
215

216
      case 'C': /* The century number. */
217
        LEGAL_ALT(ALT_E);
218
        if (!(conv_num(&bp, &i, 0, 99))) return (0);
219

220
        if (split_year) {
221
          tm->tm_year = (tm->tm_year % 100) + (i * 100);
222
        } else {
223
          tm->tm_year = i * 100;
224
          split_year = 1;
225
        }
226
        break;
227

228
      case 'd': /* The day of month. */
229
      case 'e':
230
        LEGAL_ALT(ALT_O);
231
        if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) return (0);
232
        break;
233

234
      case 'k': /* The hour (24-hour clock representation). */
235
        LEGAL_ALT(0);
236
        /* FALLTHROUGH */
237
      case 'H':
238
        LEGAL_ALT(ALT_O);
239
        if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) return (0);
240
        break;
241

242
      case 'l': /* The hour (12-hour clock representation). */
243
        LEGAL_ALT(0);
244
        /* FALLTHROUGH */
245
      case 'I':
246
        LEGAL_ALT(ALT_O);
247
        if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) return (0);
248
        if (tm->tm_hour == 12) tm->tm_hour = 0;
249
        break;
250

251
      case 'j': /* The day of year. */
252
        LEGAL_ALT(0);
253
        if (!(conv_num(&bp, &i, 1, 366))) return (0);
254
        tm->tm_yday = i - 1;
255
        break;
256

257
      case 'M': /* The minute. */
258
        LEGAL_ALT(ALT_O);
259
        if (!(conv_num(&bp, &tm->tm_min, 0, 59))) return (0);
260
        break;
261

262
      case 'm': /* The month. */
263
        LEGAL_ALT(ALT_O);
264
        if (!(conv_num(&bp, &i, 1, 12))) return (0);
265
        tm->tm_mon = i - 1;
266
        break;
267

268
      case 'p': /* The locale's equivalent of AM/PM. */
269
        LEGAL_ALT(0);
270
        /* AM? */
271
        if (strcmp(am_pm[0], bp) == 0) {
272
          if (tm->tm_hour > 11) return (0);
273

274
          bp += strlen(am_pm[0]);
275
          break;
276
        }
277
        /* PM? */
278
        else if (strcmp(am_pm[1], bp) == 0) {
279
          if (tm->tm_hour > 11) return (0);
280

281
          tm->tm_hour += 12;
282
          bp += strlen(am_pm[1]);
283
          break;
284
        }
285

286
        /* Nothing matched. */
287
        return (0);
288

289
      case 'S': /* The seconds. */
290
        LEGAL_ALT(ALT_O);
291
        if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) return (0);
292
        break;
293

294
      case 'U': /* The week of year, beginning on sunday. */
295
      case 'W': /* The week of year, beginning on monday. */
296
        LEGAL_ALT(ALT_O);
297
        /*
298
         * XXX This is bogus, as we can not assume any valid
299
         * information present in the tm structure at this
300
         * point to calculate a real value, so just check the
301
         * range for now.
302
         */
303
        if (!(conv_num(&bp, &i, 0, 53))) return (0);
304
        break;
305

306
      case 'w': /* The day of week, beginning on sunday. */
307
        LEGAL_ALT(ALT_O);
308
        if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) return (0);
309
        break;
310

311
      case 'Y': /* The year. */
312
        LEGAL_ALT(ALT_E);
313
        if (!(conv_num(&bp, &i, 0, 9999))) return (0);
314

315
        tm->tm_year = i - TM_YEAR_BASE;
316
        break;
317

318
      case 'y': /* The year within 100 years of the epoch. */
319
        LEGAL_ALT(ALT_E | ALT_O);
320
        if (!(conv_num(&bp, &i, 0, 99))) return (0);
321

322
        if (split_year) {
323
          tm->tm_year = ((tm->tm_year / 100) * 100) + i;
324
          break;
325
        }
326
        split_year = 1;
327
        if (i <= 68)
328
          tm->tm_year = i + 2000 - TM_YEAR_BASE;
329
        else
330
          tm->tm_year = i + 1900 - TM_YEAR_BASE;
331
        break;
332

333
        /*
334
         * Miscellaneous conversions.
335
         */
336
      case 'n': /* Any kind of white-space. */
337
      case 't':
338
        LEGAL_ALT(0);
339
        while (isspace(*bp)) bp++;
340
        break;
341

342
      default: /* Unknown/unsupported conversion. */
343
        return (0);
344
    }
345
  }
346

347
  /* LINTED functional specification */
348
  return ((char *)bp);
349
#else
350
  return strptime(buf, fmt, tm);
2,147,483,647✔
351
#endif
352
}
353

354
size_t taosStrfTime(char *s, size_t maxsize, char const *format, struct tm const *t) {
2,147,483,647✔
355
  if (!s || !format || !t) return 0;
2,147,483,647✔
356
  return strftime(s, maxsize, format, t);
2,147,483,647✔
357
}
358

359
int32_t taosGetTimeOfDay(struct timeval *tv) {
2,147,483,647✔
360
  if (tv == NULL) {
2,147,483,647✔
361
    return TSDB_CODE_INVALID_PARA;
101✔
362
  }
363
  int32_t code = 0;
2,147,483,647✔
364
#ifdef WINDOWS
365
  LARGE_INTEGER t;
366
  FILETIME      f;
367

368
  GetSystemTimeAsFileTime(&f);
369
  t.QuadPart = f.dwHighDateTime;
370
  t.QuadPart <<= 32;
371
  t.QuadPart |= f.dwLowDateTime;
372

373
  t.QuadPart -= TIMEEPOCH;
374
  tv->tv_sec = t.QuadPart / 10000000;
375
  tv->tv_usec = (t.QuadPart % 10000000) / 10;
376
  return 0;
377
#else
378
  code = gettimeofday(tv, NULL);
2,147,483,647✔
379
  return (-1 == code) ? (terrno = TAOS_SYSTEM_ERROR(ERRNO)) : 0;
2,147,483,647✔
380
#endif
381
}
382

383
int32_t taosTime(time_t *t) {
15,960,531✔
384
  if (t == NULL) {
15,960,531✔
385
    return TSDB_CODE_INVALID_PARA;
101✔
386
  }
387
  time_t r = time(t);
15,960,430✔
388
  if (r == (time_t)-1) {
15,960,386✔
389
    return TAOS_SYSTEM_ERROR(ERRNO);
×
390
  }
391
  return 0;
15,960,386✔
392
}
393

394
/*
395
 * mktime64 - Converts date to seconds.
396
 * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
397
 * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
398
 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
399
 *
400
 * [For the Julian calendar (which was used in Russia before 1917,
401
 * Britain & colonies before 1752, anywhere else before 1582,
402
 * and is still in use by some communities) leave out the
403
 * -year/100+year/400 terms, and add 10.]
404
 *
405
 * This algorithm was first published by Gauss (I think).
406
 *
407
 * A leap second can be indicated by calling this function with sec as
408
 * 60 (allowable under ISO 8601).  The leap second is treated the same
409
 * as the following second since they don't exist in UNIX time.
410
 *
411
 * An encoding of midnight at the end of the day as 24:00:00 - ie. midnight
412
 * tomorrow - (allowable under ISO 8601) is supported.
413
 */
414
int64_t user_mktime64(const uint32_t year, const uint32_t mon, const uint32_t day, const uint32_t hour,
202✔
415
                      const uint32_t min, const uint32_t sec, int64_t time_zone) {
416
  uint32_t _mon = mon, _year = year;
202✔
417

418
  /* 1..12 -> 11,12,1..10 */
419
  if (0 >= (int32_t)(_mon -= 2)) {
202✔
420
    _mon += 12; /* Puts Feb last since it has leap day */
101✔
421
    _year -= 1;
101✔
422
  }
423

424
  // int64_t _res = (((((int64_t) (_year/4 - _year/100 + _year/400 + 367*_mon/12 + day) +
425
  //                _year*365 - 719499)*24 + hour)*60 + min)*60 + sec);
426
  int64_t _res = 367 * ((int64_t)_mon) / 12;
202✔
427
  _res += _year / 4 - _year / 100 + _year / 400 + day + ((int64_t)_year) * 365 - 719499;
202✔
428
  _res *= 24;
202✔
429
  _res = ((_res + hour) * 60 + min) * 60 + sec;
202✔
430

431
  return _res + time_zone;
202✔
432
}
433

434
time_t taosMktime(struct tm *timep, timezone_t tz) {
2,147,483,647✔
435
#ifdef WINDOWS
436
  // Get timezone offset (correctly use the passed tz parameter)
437
  int64_t tzw = 0;
438
  if (tz != NULL) {
439
    WindowsTimezoneObj* tz_obj = (WindowsTimezoneObj*)tz;
440
    taosThreadMutexLock(&tz_obj->mutex);
441
    tzw = tz_obj->offset_seconds;
442
    taosThreadMutexUnlock(&tz_obj->mutex);
443
  } else {
444
    // Use getWindowsTimezoneOffset which reads from TZ environment variable
445
    tzw = getWindowsTimezoneOffset();
446
  }
447

448
  // Calculate timestamp using user_mktime64
449
  time_t result = user_mktime64(timep->tm_year + 1900, timep->tm_mon + 1, timep->tm_mday,
450
                                 timep->tm_hour, timep->tm_min, timep->tm_sec, tzw);
451

452
  // Set global timezone variable
453
  timezone = tzw;
454

455
  return result;
456
#elif defined(TD_ASTRA)
457
  time_t r =  mktime(timep);
458
  if (r == (time_t)-1) {
459
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
460
  }
461
  return r;
462
#else
463
  if (tz == NULL) {
2,147,483,647✔
464
    tz = getGlobalDefaultTZ();
2,147,483,647✔
465
  }
466
  time_t r = (tz != NULL ? mktime_z(tz, timep) : mktime(timep));
2,147,483,647✔
467
  if (r == (time_t)-1) {
2,147,483,647✔
468
    terrno = TAOS_SYSTEM_ERROR(ERRNO);
×
469
  }
470
  timezone = -timep->tm_gmtoff;
2,147,483,647✔
471
  return r;
2,147,483,647✔
472
#endif
473
}
474

475
struct tm *taosGmTimeR(const time_t *timep, struct tm *result) {
314,744,563✔
476
  if (timep == NULL || result == NULL) {
314,744,563✔
477
    return NULL;
212✔
478
  }
479
#ifdef WINDOWS
480
  errno_t code = gmtime_s(result, timep);
481
  return (code == 0) ? result : NULL;
482
#else
483
  return gmtime_r(timep, result);
314,758,251✔
484
#endif
485
}
486

487
time_t taosTimeGm(struct tm *tmp) {
2,147,483,647✔
488
  if (tmp == NULL) {
2,147,483,647✔
489
    return -1;
106✔
490
  }
491
#ifdef WINDOWS
492
  return _mkgmtime(tmp);
493
#elif defined(TD_ASTRA)
494
  time_t    local = mktime(tmp);
495
  struct tm local_tm = {0};
496
  taosLocalTime(&local, &local_tm, NULL, 0, NULL);
497
  struct tm utc_tm = {0};
498
  taosGmTimeR(&local, &utc_tm);
499
  time_t    offset = (local_tm.tm_hour - utc_tm.tm_hour) * 3600 + (local_tm.tm_min - utc_tm.tm_min) * 60 +
500
                  (local_tm.tm_sec - utc_tm.tm_sec);
501
  return local - offset;
502
#else
503
  return timegm(tmp);
2,147,483,647✔
504
#endif
505
}
506

507
#ifdef WINDOWS
508
static int calcDayOfYear(int y, int m, int d) {
509
  static const int days[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
510
  return days[m - 1] + d + ((m > 2 && ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0))) ? 1 : 0);
511
}
512
#endif
513

514
struct tm *taosLocalTime(const time_t *timep, struct tm *result, char *buf, int32_t bufSize, timezone_t tz) {
2,147,483,647✔
515
  struct tm *res = NULL;
2,147,483,647✔
516
  if (timep == NULL || result == NULL) {
2,147,483,647✔
517
    return NULL;
×
518
  }
519
#ifdef WINDOWS
520
  // Get timezone offset (correctly use the passed tz parameter)
521
  int64_t tz_offset = 0;
522
  if (tz != NULL) {
523
    WindowsTimezoneObj* tz_obj = (WindowsTimezoneObj*)tz;
524
    taosThreadMutexLock(&tz_obj->mutex);
525
    tz_offset = tz_obj->offset_seconds;
526
    taosThreadMutexUnlock(&tz_obj->mutex);
527
  } else {
528
    // Use getWindowsTimezoneOffset which reads from TZ environment variable
529
    tz_offset = getWindowsTimezoneOffset();
530
  }
531

532
  // Convert UTC timestamp to local time.
533
  // tz_offset is east-negative (POSIX `timezone` convention), so:
534
  //   local = utc - tz_offset  =  utc + |east_offset|
535
  // e.g. East 8 (UTC+8): tz_offset = -28800, adjusted_time = *timep + 28800.
536
  time_t adjusted_time = *timep + (-tz_offset);
537

538
  // Convert to struct tm (keep existing logic)
539
  if (adjusted_time < -2208988800LL) {
540
    if (buf != NULL) {
541
      snprintf(buf, bufSize, "NaN");
542
    }
543
    return NULL;
544
  } else if (adjusted_time < 0) {
545
    SYSTEMTIME ss, s;
546
    FILETIME   ff, f;
547

548
    LARGE_INTEGER offset;
549
    struct tm     tm1;
550
    time_t        tt = 0;
551
    if (gmtime_s(&tm1, &tt) != 0) {
552
      if (buf != NULL) {
553
        snprintf(buf, bufSize, "NaN");
554
      }
555
      return NULL;
556
    }
557
    ss.wYear = tm1.tm_year + 1900;
558
    ss.wMonth = tm1.tm_mon + 1;
559
    ss.wDay = tm1.tm_mday;
560
    ss.wHour = tm1.tm_hour;
561
    ss.wMinute = tm1.tm_min;
562
    ss.wSecond = tm1.tm_sec;
563
    ss.wMilliseconds = 0;
564
    SystemTimeToFileTime(&ss, &ff);
565
    offset.QuadPart = ff.dwHighDateTime;
566
    offset.QuadPart <<= 32;
567
    offset.QuadPart |= ff.dwLowDateTime;
568
    offset.QuadPart += adjusted_time * 10000000;
569
    f.dwLowDateTime = offset.QuadPart & 0xffffffff;
570
    f.dwHighDateTime = (offset.QuadPart >> 32) & 0xffffffff;
571
    FileTimeToSystemTime(&f, &s);
572
    result->tm_sec = s.wSecond;
573
    result->tm_min = s.wMinute;
574
    result->tm_hour = s.wHour;
575
    result->tm_mday = s.wDay;
576
    result->tm_mon = s.wMonth - 1;
577
    result->tm_year = s.wYear - 1900;
578
    result->tm_wday = s.wDayOfWeek;
579
    result->tm_yday = calcDayOfYear(s.wYear, s.wMonth, s.wDay);
580
    result->tm_isdst = 0;
581
  } else {
582
    if (gmtime_s(result, &adjusted_time) != 0) {
583
      if (buf != NULL) {
584
        snprintf(buf, bufSize, "NaN");
585
      }
586
      return NULL;
587
    }
588
  }
589

590
  // Update the global `timezone` variable (POSIX convention: east-negative, west-positive).
591
  // On non-Windows: set as `timezone = -result->tm_gmtoff` (see #else branch below).
592
  // On Windows: tz_offset already carries the east-negative value (from tz_obj->offset_seconds
593
  // or getWindowsTimezoneOffset()), so assigning it directly gives the same semantics.
594
  // External callers needing east-positive values should use taosGetTZOffsetSeconds().
595
  timezone = tz_offset;
596

597
  return result;
598
#elif defined(TD_ASTRA)
599
  res = localtime_r(timep, result);
600
  if (res == NULL && buf != NULL) {
601
    (void)snprintf(buf, bufSize, "NaN");
602
  }
603
  return res;
604
#else
605
  if (tz == NULL) {
2,147,483,647✔
606
    tz = getGlobalDefaultTZ();
2,147,483,647✔
607
  }
608
  res = (tz != NULL ? localtime_rz(tz, timep, result) : localtime_r(timep, result));
2,147,483,647✔
609
  if (res == NULL && buf != NULL) {
2,147,483,647✔
610
    (void)snprintf(buf, bufSize, "NaN");
×
611
  }
612
  timezone = -result->tm_gmtoff;
2,147,483,647✔
613
  return res;
2,147,483,647✔
614
#endif
615
}
616

617
int32_t taosGetTimestampSec() { return (int32_t)time(NULL); }
1,947,031,127✔
618

619
int32_t taosClockGetTime(int clock_id, struct timespec *pTS) {
2,147,483,647✔
620
  int32_t code = 0;
2,147,483,647✔
621
#ifdef WINDOWS
622
  if (clock_id == CLOCK_MONOTONIC) {
623
    static LARGE_INTEGER freq;
624
    static BOOL freq_init = FALSE;
625
    LARGE_INTEGER t;
626
    if (!freq_init) {
627
        QueryPerformanceFrequency(&freq);
628
        freq_init = TRUE;
629
    }
630
    QueryPerformanceCounter(&t);
631
    // 转换为秒和纳秒
632
    pTS->tv_sec = (time_t)(t.QuadPart / freq.QuadPart);
633
    pTS->tv_nsec = (long)(((t.QuadPart % freq.QuadPart) * 1000000000LL) / freq.QuadPart);
634
    return 0;
635
  } else {
636
    LARGE_INTEGER t;
637
    FILETIME      f;
638

639
    GetSystemTimeAsFileTime(&f);
640
    t.QuadPart = f.dwHighDateTime;
641
    t.QuadPart <<= 32;
642
    t.QuadPart |= f.dwLowDateTime;
643

644
    t.QuadPart -= TIMEEPOCH;
645
    pTS->tv_sec = t.QuadPart / 10000000;
646
    pTS->tv_nsec = (t.QuadPart % 10000000) * 100;
647
    return (0);
648
  }
649
#else
650
  code = clock_gettime(clock_id, pTS);
2,147,483,647✔
651
  return (-1 == code) ? (terrno = TAOS_SYSTEM_ERROR(ERRNO)) : 0;
2,147,483,647✔
652
#endif
653
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc