if (!do_locales)
setlocale(LC_TIME, "C");
char date[128];
- strftime(date, sizeof(date), t_fmt, localtime(&folder->ff->mtime));
+ mutt_date_localtime_format(date, sizeof(date), t_fmt, folder->ff->mtime);
if (!do_locales)
setlocale(LC_TIME, "");
/* preprocess $date_format to handle %Z */
{
const char *cp = NULL;
- struct tm *tm = NULL;
+ struct tm tm = { 0 };
time_t now;
int j = 0;
{
char *is = NULL;
now = time(NULL);
- tm = localtime(&now);
+ tm = mutt_date_localtime(now);
now -= (op == '(') ? e->received : e->date_sent;
is = (char *) prec;
t--;
t *= (60 * 60 * 24 * 365);
}
- t += ((tm->tm_mon * 60 * 60 * 24 * 30) + (tm->tm_mday * 60 * 60 * 24) +
- (tm->tm_hour * 60 * 60) + (tm->tm_min * 60) + tm->tm_sec);
+ t += ((tm.tm_mon * 60 * 60 * 24 * 30) + (tm.tm_mday * 60 * 60 * 24) +
+ (tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec);
break;
case 'm':
t--;
t *= (60 * 60 * 24 * 30);
}
- t += ((tm->tm_mday * 60 * 60 * 24) + (tm->tm_hour * 60 * 60) +
- (tm->tm_min * 60) + tm->tm_sec);
+ t += ((tm.tm_mday * 60 * 60 * 24) + (tm.tm_hour * 60 * 60) +
+ (tm.tm_min * 60) + tm.tm_sec);
break;
case 'w':
t--;
t *= (60 * 60 * 24 * 7);
}
- t += ((tm->tm_wday * 60 * 60 * 24) + (tm->tm_hour * 60 * 60) +
- (tm->tm_min * 60) + tm->tm_sec);
+ t += ((tm.tm_wday * 60 * 60 * 24) + (tm.tm_hour * 60 * 60) +
+ (tm.tm_min * 60) + tm.tm_sec);
break;
case 'd':
t--;
t *= (60 * 60 * 24);
}
- t += ((tm->tm_hour * 60 * 60) + (tm->tm_min * 60) + tm->tm_sec);
+ t += ((tm.tm_hour * 60 * 60) + (tm.tm_min * 60) + tm.tm_sec);
break;
case 'H':
t--;
t *= (60 * 60);
}
- t += ((tm->tm_min * 60) + tm->tm_sec);
+ t += ((tm.tm_min * 60) + tm.tm_sec);
break;
case 'M':
t--;
t *= (60);
}
- t += (tm->tm_sec);
+ t += (tm.tm_sec);
break;
default:
*p = '\0';
if ((op == '[') || (op == 'D'))
- tm = localtime(&e->date_sent);
+ tm = mutt_date_localtime(e->date_sent);
else if (op == '(')
- tm = localtime(&e->received);
+ tm = mutt_date_localtime(e->received);
else if (op == '<')
{
- now = time(NULL);
- tm = localtime(&now);
+ tm = mutt_date_localtime(MUTT_DATE_NOW);
}
else
{
now -= (e->zhours * 3600 + e->zminutes * 60);
else
now += (e->zhours * 3600 + e->zminutes * 60);
- tm = gmtime(&now);
+ tm = mutt_date_gmtime(now);
}
if (!do_locales)
setlocale(LC_TIME, "C");
- strftime(tmp, sizeof(tmp), buf, tm);
+ strftime(tmp, sizeof(tmp), buf, &tm);
if (!do_locales)
setlocale(LC_TIME, "");
* @param utc UTC time
* @retval num Seconds east of UTC
*
- * returns the seconds east of UTC given 'g' and its corresponding gmtime()
+ * returns the seconds east of UTC given 'g' and its corresponding gmtime()
* representation
*/
static time_t compute_tz(time_t g, struct tm *utc)
{
- struct tm *lt = localtime(&g);
+ struct tm lt = mutt_date_localtime(g);
time_t t;
int yday;
- t = (((lt->tm_hour - utc->tm_hour) * 60) + (lt->tm_min - utc->tm_min)) * 60;
+ t = (((lt.tm_hour - utc->tm_hour) * 60) + (lt.tm_min - utc->tm_min)) * 60;
- yday = (lt->tm_yday - utc->tm_yday);
+ yday = (lt.tm_yday - utc->tm_yday);
if (yday != 0)
{
/* This code is optimized to negative timezones (West of Greenwich) */
if ((t == TIME_T_MAX) || (t == TIME_T_MIN))
return 0;
- struct tm *ptm = NULL;
- struct tm utc;
-
- if (!t)
+ if (t == 0)
t = time(NULL);
- ptm = gmtime(&t);
- /* need to make a copy because gmtime/localtime return a pointer to
- * static memory (grr!) */
- memcpy(&utc, ptm, sizeof(utc));
- return compute_tz(t, &utc);
+
+ struct tm tm = mutt_date_gmtime(t);
+ return compute_tz(t, &tm);
}
/**
char *mutt_date_make_date(char *buf, size_t buflen)
{
time_t t = time(NULL);
- struct tm *l = localtime(&t);
+ struct tm tm = mutt_date_localtime(t);
time_t tz = mutt_date_local_tz(t);
tz /= 60;
snprintf(buf, buflen, "Date: %s, %d %s %d %02d:%02d:%02d %+03d%02d\n",
- Weekdays[l->tm_wday], l->tm_mday, Months[l->tm_mon], l->tm_year + 1900,
- l->tm_hour, l->tm_min, l->tm_sec, (int) tz / 60, (int) abs((int) tz) % 60);
+ Weekdays[tm.tm_wday], tm.tm_mday, Months[tm.tm_mon], tm.tm_year + 1900,
+ tm.tm_hour, tm.tm_min, tm.tm_sec, (int) tz / 60, (int) abs((int) tz) % 60);
return buf;
}
*/
int mutt_date_make_imap(char *buf, size_t buflen, time_t timestamp)
{
- struct tm *tm = localtime(×tamp);
+ struct tm tm = mutt_date_localtime(timestamp);
time_t tz = mutt_date_local_tz(timestamp);
tz /= 60;
- return snprintf(buf, buflen, "%02d-%s-%d %02d:%02d:%02d %+03d%02d", tm->tm_mday,
- Months[tm->tm_mon], tm->tm_year + 1900, tm->tm_hour, tm->tm_min,
- tm->tm_sec, (int) tz / 60, (int) abs((int) tz) % 60);
+ return snprintf(buf, buflen, "%02d-%s-%d %02d:%02d:%02d %+03d%02d",
+ tm.tm_mday, Months[tm.tm_mon], tm.tm_year + 1900, tm.tm_hour,
+ tm.tm_min, tm.tm_sec, (int) tz / 60, (int) abs((int) tz) % 60);
}
/**
*/
int mutt_date_make_tls(char *buf, size_t buflen, time_t timestamp)
{
- struct tm *tm = gmtime(×tamp);
+ struct tm tm = mutt_date_gmtime(timestamp);
return snprintf(buf, buflen, "%s, %d %s %d %02d:%02d:%02d UTC",
- Weekdays[tm->tm_wday], tm->tm_mday, Months[tm->tm_mon],
- tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec);
+ Weekdays[tm.tm_wday], tm.tm_mday, Months[tm.tm_mon],
+ tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
}
/**
return now + timeout;
}
+
+/**
+ * mutt_date_localtime - Converts calendar time to a broken-down time structure expressed in user timezone.
+ * @param t Time
+ * @retval tm Broken-down time representation
+ *
+ * Uses current time if t is #MUTT_DATE_NOW
+ */
+struct tm mutt_date_localtime(time_t t)
+{
+ struct tm tm = { 0 };
+
+ if (t == MUTT_DATE_NOW)
+ t = time(NULL);
+
+ localtime_r(&t, &tm);
+ return tm;
+}
+
+/**
+ * mutt_date_gmtime - Converts calendar time to a broken-down time structure expressed in UTC timezone.
+ * @param t Time
+ * @retval tm Broken-down time representation
+ *
+ * Uses current time if t is #MUTT_DATE_NOW
+ */
+struct tm mutt_date_gmtime(time_t t)
+{
+ struct tm tm = { 0 };
+
+ if (t == MUTT_DATE_NOW)
+ t = time(NULL);
+
+ gmtime_r(&t, &tm);
+ return tm;
+}
+
+/**
+ * mutt_date_localtime_format - Format localtime
+ * @param buf Buffer to store formated time
+ * @param buflen Buffer size
+ * @param format Format to apply
+ * @param t Time to format
+ * @retval num Number of Bytes added to buffer, excluding null byte.
+ */
+size_t mutt_date_localtime_format(char *buf, size_t buflen, char *format, time_t t)
+{
+ struct tm tm = mutt_date_localtime(t);
+ return strftime(buf, buflen, format, &tm);
+}
#include <stdbool.h>
#include <time.h>
+#define MUTT_DATE_NOW -9999 ///< Constant representing the 'current time', see: mutt_date_gmtime(), mutt_date_localtime()
+
/**
* struct Tz - List of recognised Timezones
*/
bool zoccident; /**< True if west of UTC, False if East */
};
-time_t mutt_date_add_timeout(time_t now, long timeout);
-int mutt_date_check_month(const char *s);
-bool mutt_date_is_day_name(const char *s);
-time_t mutt_date_local_tz(time_t t);
-char * mutt_date_make_date(char *buf, size_t buflen);
-int mutt_date_make_imap(char *buf, size_t buflen, time_t timestamp);
-time_t mutt_date_make_time(struct tm *t, int local);
-int mutt_date_make_tls(char *buf, size_t buflen, time_t timestamp);
-void mutt_date_normalize_time(struct tm *tm);
-time_t mutt_date_parse_date(const char *s, struct Tz *tz_out);
-time_t mutt_date_parse_imap(const char *s);
+time_t mutt_date_add_timeout(time_t now, long timeout);
+int mutt_date_check_month(const char *s);
+struct tm mutt_date_gmtime(time_t t);
+bool mutt_date_is_day_name(const char *s);
+size_t mutt_date_localtime_format(char *buf, size_t buflen, char *format, time_t t);
+struct tm mutt_date_localtime(time_t t);
+time_t mutt_date_local_tz(time_t t);
+char * mutt_date_make_date(char *buf, size_t buflen);
+int mutt_date_make_imap(char *buf, size_t buflen, time_t timestamp);
+time_t mutt_date_make_time(struct tm *t, int local);
+int mutt_date_make_tls(char *buf, size_t buflen, time_t timestamp);
+void mutt_date_normalize_time(struct tm *tm);
+time_t mutt_date_parse_date(const char *s, struct Tz *tz_out);
+time_t mutt_date_parse_imap(const char *s);
#endif /* MUTT_LIB_DATE_H */
#include <time.h>
#include <unistd.h>
#include "logging.h"
+#include "date.h"
#include "file.h"
#include "memory.h"
#include "message.h"
if (stamp != last)
{
- strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", localtime(&stamp));
+ mutt_date_localtime_format(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", stamp);
last = stamp;
}
struct LogLine *ll = NULL;
STAILQ_FOREACH(ll, &LogQueue, entries)
{
- strftime(buf, sizeof(buf), "%H:%M:%S", localtime(&ll->time));
+ mutt_date_localtime_format(buf, sizeof(buf), "%H:%M:%S", ll->time);
fprintf(fp, "[%s]<%c> %s", buf, LevelAbbr[ll->level + 3], ll->message);
if (ll->level <= 0)
fputs("\n", fp);
*/
void crypt_current_time(struct State *s, const char *app_name)
{
- time_t t;
char p[256], tmp[256];
if (!WithCrypto)
if (C_CryptTimestamp)
{
- t = time(NULL);
- strftime(p, sizeof(p), _(" (current time: %c)"), localtime(&t));
+ mutt_date_localtime_format(p, sizeof(p), _(" (current time: %c)"), MUTT_DATE_NOW);
}
else
*p = '\0';
static void print_time(time_t t, struct State *s)
{
char p[256];
-
- strftime(p, sizeof(p), nl_langinfo(D_T_FMT), localtime(&t));
+ mutt_date_localtime_format(p, sizeof(p), nl_langinfo(D_T_FMT), t);
state_puts(p, s);
}
if (len > 8)
shortid += len - 8;
tt = subkey->timestamp;
- strftime(date, sizeof(date), "%Y-%m-%d", localtime(&tt));
+ mutt_date_localtime_format(date, sizeof(date), "%Y-%m-%d", tt);
if (!more)
{
{
char buf2[128];
bool do_locales = true;
- struct tm *tm = NULL;
+ struct tm tm = { 0 };
size_t len;
char *p = buf;
}
*p = '\0';
- {
- time_t tt = 0;
-
- if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
- tt = key->kobj->subkeys->timestamp;
-
- tm = localtime(&tt);
- }
+ if (key->kobj->subkeys && (key->kobj->subkeys->timestamp > 0))
+ tm = mutt_date_localtime(key->kobj->subkeys->timestamp);
+ else
+ tm = mutt_date_localtime(0); // Default to 1970-01-01
if (!do_locales)
setlocale(LC_TIME, "C");
- strftime(buf2, sizeof(buf2), buf, tm);
+ strftime(buf2, sizeof(buf2), buf, &tm);
if (!do_locales)
setlocale(LC_TIME, "");
int idx;
const char *s = NULL, *s2 = NULL;
time_t tt = 0;
- struct tm *tm = NULL;
char shortbuf[128];
unsigned long aval = 0;
const char *delim = NULL;
{
tt = key->subkeys->timestamp;
- tm = localtime(&tt);
- strftime(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tm);
+ mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
_(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
}
{
tt = key->subkeys->expires;
- tm = localtime(&tt);
- strftime(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tm);
+ mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO],
_(KeyInfoPrompts[KIP_VALID_TO]), shortbuf);
}
{
tt = subkey->timestamp;
- tm = localtime(&tt);
- strftime(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tm);
+ mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_FROM],
_(KeyInfoPrompts[KIP_VALID_FROM]), shortbuf);
}
{
tt = subkey->expires;
- tm = localtime(&tt);
- strftime(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tm);
+ mutt_date_localtime_format(shortbuf, sizeof(shortbuf), nl_langinfo(D_T_FMT), tt);
fprintf(fp, "%*s%s\n", KeyInfoPadding[KIP_VALID_TO],
_(KeyInfoPrompts[KIP_VALID_TO]), shortbuf);
}
{
char buf2[128];
bool do_locales = true;
- struct tm *tm = NULL;
size_t len;
char *p = buf;
}
*p = '\0';
- tm = localtime(&key->gen_time);
-
if (!do_locales)
setlocale(LC_TIME, "C");
- strftime(buf2, sizeof(buf2), buf, tm);
+ mutt_date_localtime_format(buf2, sizeof(buf2), buf, key->gen_time);
if (!do_locales)
setlocale(LC_TIME, "");
{
struct NntpMboxData tmp_mdata;
time_t now;
- struct tm *tm = NULL;
char buf[1024];
char *msg = _("Checking for new newsgroups...");
unsigned int i;
else
tmp_mdata.group = NULL;
i = adata->groups_num;
- tm = gmtime(&adata->newgroups_time);
+ struct tm tm = mutt_date_gmtime(adata->newgroups_time);
snprintf(buf, sizeof(buf), "NEWGROUPS %02d%02d%02d %02d%02d%02d GMT\r\n",
- tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour,
- tm->tm_min, tm->tm_sec);
+ tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
rc = nntp_fetch_lines(&tmp_mdata, buf, sizeof(buf), msg, nntp_add_group, adata);
if (rc)
{
static const char *get_date(const char *s, struct tm *t, struct Buffer *err)
{
char *p = NULL;
- time_t now = time(NULL);
- struct tm *tm = localtime(&now);
+ struct tm tm = mutt_date_localtime(MUTT_DATE_NOW);
t->tm_mday = strtol(s, &p, 10);
if ((t->tm_mday < 1) || (t->tm_mday > 31))
if (*p != '/')
{
/* fill in today's month and year */
- t->tm_mon = tm->tm_mon;
- t->tm_year = tm->tm_year;
+ t->tm_mon = tm.tm_mon;
+ t->tm_year = tm.tm_year;
return p;
}
p++;
}
if (*p != '/')
{
- t->tm_year = tm->tm_year;
+ t->tm_year = tm.tm_year;
return p;
}
p++;
* <3d less than three days ago
* >3d more than three days ago
* =3d exactly three days ago */
- time_t now = time(NULL);
- struct tm *tm = localtime(&now);
+ struct tm *tm = NULL;
bool exact = false;
if (buf.data[0] == '<')
{
- memcpy(&min, tm, sizeof(min));
+ min = mutt_date_localtime(MUTT_DATE_NOW);
tm = &min;
}
else
{
- memcpy(&max, tm, sizeof(max));
+ max = mutt_date_localtime(MUTT_DATE_NOW);
tm = &max;
if (buf.data[0] == '=')
if (!have_min)
{ /* save base minimum and set current date, e.g. for "-3d+1d" */
- time_t now = time(NULL);
- struct tm *tm = localtime(&now);
memcpy(&base_min, &min, sizeof(base_min));
- memcpy(&min, tm, sizeof(min));
+ min = mutt_date_localtime(MUTT_DATE_NOW);
min.tm_hour = 0;
min.tm_sec = 0;
min.tm_min = 0;
static char *gen_msgid(void)
{
char buf[128];
- time_t now;
unsigned char rndid[MUTT_RANDTAG_LEN + 1];
mutt_rand_base32(rndid, sizeof(rndid) - 1);
rndid[MUTT_RANDTAG_LEN] = 0;
- now = time(NULL);
- struct tm *tm = gmtime(&now);
const char *fqdn = mutt_fqdn(false);
if (!fqdn)
fqdn = NONULL(ShortHostname);
- snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm->tm_year + 1900,
- tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, rndid, fqdn);
+ struct tm tm = mutt_date_gmtime(MUTT_DATE_NOW);
+ snprintf(buf, sizeof(buf), "<%d%02d%02d%02d%02d%02d.%s@%s>", tm.tm_year + 1900,
+ tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, rndid, fqdn);
return mutt_str_strdup(buf);
}