size_t gstrftime(char *s, size_t bsz, const char *fmt, double l_clock) { struct tm tm; double usec; ggmtime(&tm, l_clock); usec = l_clock - (double)floor(l_clock); return xstrftime(s, bsz, fmt, &tm, usec, l_clock); }
size_t gstrftime(char *s, size_t bsz, const char *fmt, double l_clock) { struct tm tm; ggmtime(&tm, l_clock); #if 0 if ((tm.tm_zone = (char *) malloc(strlen(xtm->tm_zone) + 1))) strcpy(tm.tm_zone, xtm->tm_zone); /* printf("zone: %s - %s\n",tm.tm_zone,xtm->tm_zone); */ #endif return xstrftime(s, bsz, fmt, &tm); }
int main(int argc, char *argv[]) { char output[80]; if (argc < 2) { fputs("usage : test 'format' ['time']\n", stderr); exit(EXIT_FAILURE); } if (argc == 2) { struct timeb now; struct tm *tm; ftime(&now); tm = gmtime(&now.time); xstrftime(output, 80, argv[1], tm); puts(output); } else { struct tm tm; gstrptime(argv[2], argv[1], &tm); puts(asctime(&tm)); } exit(EXIT_SUCCESS); }
static void print_status_info(const StatusInfo *i) { char a[FORMAT_TIMESTAMP_MAX]; struct tm tm; time_t sec; bool have_time = false; const char *old_tz = NULL, *tz; int r; assert(i); /* Save the old $TZ */ tz = getenv("TZ"); if (tz) old_tz = strdupa(tz); /* Set the new $TZ */ if (setenv("TZ", isempty(i->timezone) ? "UTC" : i->timezone, true) < 0) log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m"); else tzset(); if (i->time != 0) { sec = (time_t) (i->time / USEC_PER_SEC); have_time = true; } else if (IN_SET(arg_transport, BUS_TRANSPORT_LOCAL, BUS_TRANSPORT_MACHINE)) { sec = time(NULL); have_time = true; } else log_warning("Could not get time from timedated and not operating locally, ignoring."); if (have_time) { xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)); printf(" Local time: %.*s\n", (int) sizeof(a), a); xstrftime(a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)); printf(" Universal time: %.*s\n", (int) sizeof(a), a); } else { printf(" Local time: %s\n", "n/a"); printf(" Universal time: %s\n", "n/a"); } if (i->rtc_time > 0) { time_t rtc_sec; rtc_sec = (time_t) (i->rtc_time / USEC_PER_SEC); xstrftime(a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm)); printf(" RTC time: %.*s\n", (int) sizeof(a), a); } else printf(" RTC time: %s\n", "n/a"); if (have_time) xstrftime(a, "%Z, %z", localtime_r(&sec, &tm)); /* Restore the $TZ */ if (old_tz) r = setenv("TZ", old_tz, true); else r = unsetenv("TZ"); if (r < 0) log_warning_errno(errno, "Failed to set TZ environment variable, ignoring: %m"); else tzset(); printf(" Time zone: %s (%.*s)\n" " Network time on: %s\n" "NTP synchronized: %s\n" " RTC in local TZ: %s\n", strna(i->timezone), (int) sizeof(a), have_time ? a : "n/a", i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a", yes_no(i->ntp_synced), yes_no(i->rtc_local)); if (i->rtc_local) printf("\n%s" "Warning: The system is configured to read the RTC time in the local time zone.\n" " This mode can not be fully supported. It will create various problems\n" " with time zone changes and daylight saving time adjustments. The RTC\n" " time is never updated, it relies on external facilities to maintain it.\n" " If at all possible, use RTC in UTC by calling\n" " 'timedatectl set-local-rtc 0'.%s\n", ansi_highlight(), ansi_normal()); }
static ssize_t _popul_ehdr(struct archive_string *tgt, size_t tsz, warc_essential_hdr_t hdr) { static const char _ver[] = "WARC/1.0\r\n"; static const char * const _typ[LAST_WT] = { NULL, "warcinfo", "metadata", "resource", NULL }; char std_uuid[48U]; if (hdr.type == WT_NONE || hdr.type > WT_RSRC) { /* brilliant, how exactly did we get here? */ return -1; } archive_strcpy(tgt, _ver); archive_string_sprintf(tgt, "WARC-Type: %s\r\n", _typ[hdr.type]); if (hdr.tgturi != NULL) { /* check if there's a xyz:// */ static const char _uri[] = ""; static const char _fil[] = "file://"; const char *u; char *chk = strchr(hdr.tgturi, ':'); if (chk != NULL && chk[1U] == '/' && chk[2U] == '/') { /* yep, it's definitely a URI */ u = _uri; } else { /* hm, best to prepend file:// then */ u = _fil; } archive_string_sprintf(tgt, "WARC-Target-URI: %s%s\r\n", u, hdr.tgturi); } /* record time is usually when the http is sent off, * just treat the archive writing as such for a moment */ xstrftime(tgt, "WARC-Date: %Y-%m-%dT%H:%M:%SZ\r\n", hdr.rtime); /* while we're at it, record the mtime */ xstrftime(tgt, "Last-Modified: %Y-%m-%dT%H:%M:%SZ\r\n", hdr.mtime); if (hdr.recid == NULL) { /* generate one, grrrr */ warc_uuid_t u; _gen_uuid(&u); /* Unfortunately, archive_string_sprintf does not * handle the minimum number following '%'. * So we have to use snprintf function here instead * of archive_string_snprintf function. */ #if defined(_WIN32) && !defined(__CYGWIN__) && !( defined(_MSC_VER) && _MSC_VER >= 1900) #define snprintf _snprintf #endif snprintf( std_uuid, sizeof(std_uuid), "<urn:uuid:%08x-%04x-%04x-%04x-%04x%08x>", u.u[0U], u.u[1U] >> 16U, u.u[1U] & 0xffffU, u.u[2U] >> 16U, u.u[2U] & 0xffffU, u.u[3U]); hdr.recid = std_uuid; }
static size_t xstrftime( char *str, /* output buffer */ size_t bsz, /* space available */ const char *fmt, struct tm *tm, double usec, double fulltime) { size_t l = 0; /* chars written so far */ int incr = 0; /* chars just written */ char *s = str; TBOOLEAN sign_printed = FALSE; memset(str, '\0', bsz); while (*fmt != '\0') { if (*fmt != '%') { if (l >= bsz-1) return 0; *s++ = *fmt++; l++; } else { /* set up format modifiers */ int w = 0; int z = 0; int p = 0; if (*++fmt == '0') { z = 1; ++fmt; } while (*fmt >= '0' && *fmt <= '9') { w = w * 10 + (*fmt - '0'); ++fmt; } if (*fmt == '.') { ++fmt; while (*fmt >= '0' && *fmt <= '9') { p = p * 10 + (*fmt - '0'); ++fmt; } if (p > 6) p = 6; } switch (*fmt++) { /* some shorthands : check that there is space in the * output string. */ #define CHECK_SPACE(n) do { \ if ((l+(n)) > bsz) return 0; \ } while (0) /* copy a fixed string, checking that there's room */ #define COPY_STRING(z) do { \ CHECK_SPACE(strlen(z)) ; \ strcpy(s, z); \ } while (0) /* format a string, using default spec if none given w * and z are width and zero-flag dw and dz are the * defaults for these In fact, CHECK_SPACE(w) is not a * sufficient test, since sprintf("%2d", 365) outputs * three characters */ #define FORMAT_STRING(dz, dw, x) do { \ if (w==0) { \ w=(dw); \ if (!z) \ z=(dz); \ } \ incr = snprintf(s, bsz-l-1, z ? "%0*d" : "%*d", w, (x)); \ CHECK_SPACE(incr); \ } while(0) case '%': CHECK_SPACE(1); *s = '%'; break; case 'a': COPY_STRING(abbrev_day_names[tm->tm_wday]); break; case 'A': COPY_STRING(full_day_names[tm->tm_wday]); break; case 'b': case 'h': COPY_STRING(abbrev_month_names[tm->tm_mon]); break; case 'B': COPY_STRING(full_month_names[tm->tm_mon]); break; case 'd': FORMAT_STRING(1, 2, tm->tm_mday); /* %02d */ break; case 'D': if (!xstrftime(s, bsz - l, "%m/%d/%y", tm, 0., fulltime)) return 0; break; case 'F': if (!xstrftime(s, bsz - l, "%Y-%m-%d", tm, 0., fulltime)) return 0; break; case 'H': FORMAT_STRING(1, 2, tm->tm_hour); /* %02d */ break; case 'I': FORMAT_STRING(1, 2, (tm->tm_hour + 11) % 12 + 1); /* %02d */ break; case 'j': FORMAT_STRING(1, 3, tm->tm_yday + 1); /* %03d */ break; /* not in linux strftime man page. Not really needed now */ case 'k': FORMAT_STRING(0, 2, tm->tm_hour); /* %2d */ break; case 'l': FORMAT_STRING(0, 2, (tm->tm_hour + 11) % 12 + 1); /* %2d */ break; case 'm': FORMAT_STRING(1, 2, tm->tm_mon + 1); /* %02d */ break; case 'M': FORMAT_STRING(1, 2, tm->tm_min); /* %02d */ break; case 'p': CHECK_SPACE(2); strcpy(s, (tm->tm_hour < 12) ? "am" : "pm"); break; case 'r': if (!xstrftime(s, bsz - l, "%I:%M:%S %p", tm, 0., fulltime)) return 0; break; case 'R': if (!xstrftime(s, bsz - l, "%H:%M", tm, 0., fulltime)) return 0; break; case 's': CHECK_SPACE(12); /* large enough for year 9999 */ sprintf(s, "%.0f", gtimegm(tm)); break; case 'S': FORMAT_STRING(1, 2, tm->tm_sec); /* %02d */ /* EAM FIXME - need to implement an actual format specifier */ if (p > 0) { double base = pow(10., (double)p); int msec = floor(0.5 + base * usec); char *f = &s[strlen(s)]; CHECK_SPACE(p+1); sprintf(f, ".%0*d", p, msec<(int)base?msec:(int)base-1); } break; case 'T': if (!xstrftime(s, bsz - l, "%H:%M:%S", tm, 0., fulltime)) return 0; break; case 't': /* Time (as opposed to Date) formats */ { int tminute, tsecond; switch (*fmt++) { case 'H': /* +/- fractional hours (not wrapped at 24h) */ if (p > 0) { incr = snprintf(s, bsz-l-1, "%*.*f", w, p, fulltime/3600.); CHECK_SPACE(incr); break; } /* Set flag in case minutes come next */ if (fulltime < 0) { CHECK_SPACE(1); /* the minus sign */ sign_printed = TRUE; *s++ = '-'; l++; } /* +/- integral hour truncated toward zero */ sprintf(s, "%0*d", w, (int)floor(fabs(fulltime/3600.))); break; case 'M': /* +/- fractional minutes (not wrapped at 60m) */ if (p > 0) { incr = snprintf(s, bsz-l-1, "%*.*f", w, p, sign_printed ? fabs(fulltime)/60. : fulltime/60.); CHECK_SPACE(incr); break; } /* +/- integral minute truncated toward zero */ tminute = floor(60. * (fabs(fulltime/3600.) - floor(fabs(fulltime/3600.)))); if (fulltime < 0) { if (!sign_printed) { sign_printed = TRUE; *s++ = '-'; l++; } } FORMAT_STRING(1, 2, tminute); /* %02d */ break; case 'S': /* +/- fractional seconds */ tsecond = floor(60. * (fabs(fulltime/60.) - floor(fabs(fulltime/60.)))); if (fulltime < 0) { if (usec > 0) usec = 1.0 - usec; if (!sign_printed) { *s++ = '-'; l++; } } FORMAT_STRING(1, 2, tsecond); /* %02d */ if (p > 0) { double base = pow(10., (double)p); int msec = floor(0.5 + base * usec); char *f = &s[strlen(s)]; CHECK_SPACE(p+1); sprintf(f, ".%0*d", p, msec<(int)base?msec:(int)base-1); } break; default: break; } break; } case 'W': /* mon 1 day of week */ { int week; if (tm->tm_yday <= tm->tm_wday) { week = 1; if ((tm->tm_mday - tm->tm_yday) > 4) { week = 52; } if (tm->tm_yday == tm->tm_wday && tm->tm_wday == 0) week = 52; } else { /* sun prev week */ int bw = tm->tm_yday - tm->tm_wday; if (tm->tm_wday > 0) bw += 7; /* sun end of week */ week = (int) bw / 7; if ((bw % 7) > 2) /* jan 1 is before friday */ week++; } FORMAT_STRING(1, 2, week); /* %02d */ break; } case 'U': /* sun 1 day of week */ { int week, bw; if (tm->tm_yday <= tm->tm_wday) { week = 1; if ((tm->tm_mday - tm->tm_yday) > 4) { week = 52; } } else { /* sat prev week */ bw = tm->tm_yday - tm->tm_wday - 1; if (tm->tm_wday >= 0) bw += 7; /* sat end of week */ week = (int) bw / 7; if ((bw % 7) > 1) { /* jan 1 is before friday */ week++; } } FORMAT_STRING(1, 2, week); /* %02d */ break; } case 'w': /* day of week, sun=0 */ FORMAT_STRING(1, 2, tm->tm_wday); /* %02d */ break; case 'y': FORMAT_STRING(1, 2, tm->tm_year % 100); /* %02d */ break; case 'Y': FORMAT_STRING(1, 4, tm->tm_year); /* %04d */ break; } /* switch */ while (*s != '\0') { s++; l++; } #undef CHECK_SPACE #undef COPY_STRING #undef FORMAT_STRING } /* switch(fmt letter) */ } /* if(fmt letter not '%') */ return (l); }
static void print_status_info(const StatusInfo *i) { char a[FORMAT_TIMESTAMP_MAX]; char b[FORMAT_TIMESTAMP_MAX]; char s[32]; struct tm tm; time_t sec; bool have_time = false; _cleanup_free_ char *zc = NULL, *zn = NULL; time_t t, tc, tn; int dn = 0; bool is_dstc = false, is_dstn = false; int r; assert(i); /* Enforce the values of /etc/localtime */ if (getenv("TZ")) { fprintf(stderr, "Warning: Ignoring the TZ variable. Reading the system's time zone setting only.\n\n"); unsetenv("TZ"); } if (i->time != 0) { sec = (time_t) (i->time / USEC_PER_SEC); have_time = true; } else if (arg_transport == BUS_TRANSPORT_LOCAL) { sec = time(NULL); have_time = true; } else fprintf(stderr, "Warning: Could not get time from timedated and not operating locally.\n\n"); if (have_time) { xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&sec, &tm)); printf(" Local time: %.*s\n", (int) sizeof(a), a); xstrftime(a, "%a %Y-%m-%d %H:%M:%S UTC", gmtime_r(&sec, &tm)); printf(" Universal time: %.*s\n", (int) sizeof(a), a); } else { printf(" Local time: %s\n", "n/a"); printf(" Universal time: %s\n", "n/a"); } if (i->rtc_time > 0) { time_t rtc_sec; rtc_sec = (time_t)(i->rtc_time / USEC_PER_SEC); xstrftime(a, "%a %Y-%m-%d %H:%M:%S", gmtime_r(&rtc_sec, &tm)); printf(" RTC time: %.*s\n", (int) sizeof(a), a); } else printf(" RTC time: %s\n", "n/a"); if (have_time) xstrftime(a, "%Z, %z", localtime_r(&sec, &tm)); printf(" Time zone: %s (%.*s)\n" " NTP enabled: %s\n" "NTP synchronized: %s\n" " RTC in local TZ: %s\n", strna(i->timezone), (int) sizeof(a), have_time ? a : "n/a", i->ntp_capable ? yes_no(i->ntp_enabled) : "n/a", yes_no(i->ntp_synced), yes_no(i->rtc_local)); if (have_time) { r = time_get_dst(sec, "/etc/localtime", &tc, &zc, &is_dstc, &tn, &dn, &zn, &is_dstn); if (r < 0) printf(" DST active: %s\n", "n/a"); else { printf(" DST active: %s\n", yes_no(is_dstc)); t = tc - 1; xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)); xstrftime(b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tc, &tm)); printf(" Last DST change: DST %s at\n" " %.*s\n" " %.*s\n", is_dstc ? "began" : "ended", (int) sizeof(a), a, (int) sizeof(b), b); t = tn - 1; xstrftime(a, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&t, &tm)); xstrftime(b, "%a %Y-%m-%d %H:%M:%S %Z", localtime_r(&tn, &tm)); printf(" Next DST change: DST %s (the clock jumps %s) at\n" " %.*s\n" " %.*s\n", is_dstn ? "begins" : "ends", jump_str(dn, s, sizeof(s)), (int) sizeof(a), a, (int) sizeof(b), b); } } else printf(" DST active: %s\n", yes_no(is_dstc)); if (i->rtc_local) fputs("\n" ANSI_HIGHLIGHT_ON "Warning: The system is configured to read the RTC time in the local time zone. This\n" " mode can not be fully supported. It will create various problems with time\n" " zone changes and daylight saving time adjustments. The RTC time is never updated,\n" " it relies on external facilities to maintain it. If at all possible, use\n" " RTC in UTC by calling 'timedatectl set-local-rtc 0'" ANSI_HIGHLIGHT_OFF ".\n", stdout); }
static size_t xstrftime( char *str, /* output buffer */ size_t bsz, /* space available */ const char *fmt, struct tm *tm) { size_t l = 0; /* chars written so far */ char *s = str; memset(s, '\0', bsz); while (*fmt != '\0') { if (*fmt != '%') { if (l >= bsz) return (0); *s++ = *fmt++; l++; } else { /* set up format modifiers */ int w = 0; int z = 0; if (*++fmt == '0') { z = 1; ++fmt; } while (*fmt >= '0' && *fmt <= '9') { w = w * 10 + (*fmt - '0'); ++fmt; } switch (*fmt++) { /* some shorthands : check that there is space in the * output string. */ #define CHECK_SPACE(n) do { \ if ((l+(n)) > bsz) return 0; \ } while (0) /* copy a fixed string, checking that there's room */ #define COPY_STRING(z) do { \ CHECK_SPACE(strlen(z)) ; \ strcpy(s, z); \ } while (0) /* format a string, using default spec if none given w * and z are width and zero-flag dw and dz are the * defaults for these In fact, CHECK_SPACE(w) is not a * sufficient test, since sprintf("%2d", 365) outputs * three characters */ #define FORMAT_STRING(dz, dw, x) do { \ if (w==0) { \ w=(dw); \ if (!z) \ z=(dz); \ } \ CHECK_SPACE(w); \ sprintf(s, z ? "%0*d" : "%*d", w, (x)); \ } while(0) case '%': CHECK_SPACE(1); *s = '%'; break; case 'a': COPY_STRING(abbrev_day_names[tm->tm_wday]); break; case 'A': COPY_STRING(full_day_names[tm->tm_wday]); break; case 'b': case 'h': COPY_STRING(abbrev_month_names[tm->tm_mon]); break; case 'B': COPY_STRING(full_month_names[tm->tm_mon]); break; #if 0 /* %x not currently supported, so neither is c */ case 'c': if (!xstrftime(s, bsz - l, "%x %X", tm)) return (0); break; #endif case 'd': FORMAT_STRING(1, 2, tm->tm_mday); /* %02d */ break; case 'D': if (!xstrftime(s, bsz - l, "%m/%d/%y", tm)) return (0); break; case 'F': if (!xstrftime(s, bsz - l, "%Y-%m-%d", tm)) return (0); break; case 'H': FORMAT_STRING(1, 2, tm->tm_hour); /* %02d */ break; case 'I': FORMAT_STRING(1, 2, (tm->tm_hour + 11) % 12 + 1); /* %02d */ break; case 'j': FORMAT_STRING(1, 3, tm->tm_yday + 1); /* %03d */ break; /* not in linux strftime man page. Not really needed now */ case 'k': FORMAT_STRING(0, 2, tm->tm_hour); /* %2d */ break; case 'l': FORMAT_STRING(0, 2, (tm->tm_hour + 11) % 12 + 1); /* %2d */ break; case 'm': FORMAT_STRING(1, 2, tm->tm_mon + 1); /* %02d */ break; case 'M': FORMAT_STRING(1, 2, tm->tm_min); /* %02d */ break; case 'p': CHECK_SPACE(2); strcpy(s, (tm->tm_hour < 12) ? "am" : "pm"); break; case 'r': if (!xstrftime(s, bsz - l, "%I:%M:%S %p", tm)) return (0); break; case 'R': if (!xstrftime(s, bsz - l, "%H:%M", tm)) return (0); break; case 'S': FORMAT_STRING(1, 2, tm->tm_sec); /* %02d */ break; case 'T': if (!xstrftime(s, bsz - l, "%H:%M:%S", tm)) return (0); break; case 'W': /* mon 1 day of week */ { int week; if (tm->tm_yday <= tm->tm_wday) { week = 1; if ((tm->tm_mday - tm->tm_yday) > 4) { week = 52; } if (tm->tm_yday == tm->tm_wday && tm->tm_wday == 0) week = 52; } else { /* sun prev week */ int bw = tm->tm_yday - tm->tm_wday; if (tm->tm_wday > 0) bw += 7; /* sun end of week */ week = (int) bw / 7; if ((bw % 7) > 2) /* jan 1 is before friday */ week++; } FORMAT_STRING(1, 2, week); /* %02d */ break; } case 'U': /* sun 1 day of week */ { int week, bw; if (tm->tm_yday <= tm->tm_wday) { week = 1; if ((tm->tm_mday - tm->tm_yday) > 4) { week = 52; } } else { /* sat prev week */ bw = tm->tm_yday - tm->tm_wday - 1; if (tm->tm_wday >= 0) bw += 7; /* sat end of week */ week = (int) bw / 7; if ((bw % 7) > 1) { /* jan 1 is before friday */ week++; } } FORMAT_STRING(1, 2, week); /* %02d */ break; } case 'w': /* day of week, sun=0 */ FORMAT_STRING(1, 2, tm->tm_wday); /* %02d */ break; case 'y': FORMAT_STRING(1, 2, tm->tm_year % 100); /* %02d */ break; case 'Y': FORMAT_STRING(1, 4, tm->tm_year); /* %04d */ break; #if 0 case 'Z': COPY_STRING(tm->tm_zone); break; #endif } /* switch */ while (*s != '\0') { s++; l++; } #undef CHECK_SPACE #undef COPY_STRING #undef FORMAT_STRING } /* switch(fmt letter) */ } /* if(fmt letter not '%') */ return (l); }