NeoMutt  2019-12-07-60-g0cfa53
Teaching an old dog new tricks
DOXYGEN
date.c File Reference

Time and date handling routines. More...

#include "config.h"
#include <ctype.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include "date.h"
#include "logging.h"
#include "memory.h"
#include "string2.h"
+ Include dependency graph for date.c:

Go to the source code of this file.

Functions

static time_t compute_tz (time_t g, struct tm *utc)
 Calculate the number of seconds east of UTC. More...
 
static int is_leap_year_feb (struct tm *tm)
 Is a given February in a leap year. More...
 
static const char * uncomment_timezone (char *buf, size_t buflen, const char *tz)
 Strip ()s from a timezone string. More...
 
time_t mutt_date_local_tz (time_t t)
 Calculate the local timezone in seconds east of UTC. More...
 
time_t mutt_date_make_time (struct tm *t, bool local)
 Convert struct tm to time_t More...
 
void mutt_date_normalize_time (struct tm *tm)
 Fix the contents of a struct tm. More...
 
char * mutt_date_make_date (char *buf, size_t buflen)
 Write a date in RFC822 format to a buffer. More...
 
int mutt_date_check_month (const char *s)
 Is the string a valid month name. More...
 
time_t mutt_date_epoch (void)
 Return the number of seconds since the Unix epoch. More...
 
uint64_t mutt_date_epoch_ms (void)
 Return the number of milliseconds since the Unix epoch. More...
 
bool mutt_date_is_day_name (const char *s)
 Is the string a valid day name. More...
 
time_t mutt_date_parse_date (const char *s, struct Tz *tz_out)
 Parse a date string in RFC822 format. More...
 
int mutt_date_make_imap (char *buf, size_t buflen, time_t timestamp)
 Format date in IMAP style: DD-MMM-YYYY HH:MM:SS +ZZzz. More...
 
int mutt_date_make_tls (char *buf, size_t buflen, time_t timestamp)
 Format date in TLS certificate verification style. More...
 
time_t mutt_date_parse_imap (const char *s)
 Parse date of the form: DD-MMM-YYYY HH:MM:SS +ZZzz. More...
 
time_t mutt_date_add_timeout (time_t now, long timeout)
 Safely add a timeout to a given time_t value. More...
 
struct tm mutt_date_localtime (time_t t)
 Converts calendar time to a broken-down time structure expressed in user timezone. More...
 
struct tm mutt_date_gmtime (time_t t)
 Converts calendar time to a broken-down time structure expressed in UTC timezone. More...
 
size_t mutt_date_localtime_format (char *buf, size_t buflen, const char *format, time_t t)
 Format localtime. More...
 
void mutt_date_sleep_ms (size_t ms)
 Sleep for milliseconds. More...
 

Variables

static const char *const Weekdays []
 Day of the week (abbreviated) More...
 
static const char *const Months []
 Months of the year (abbreviated) More...
 
static const struct Tz TimeZones []
 Lookup table of Time Zones. More...
 

Detailed Description

Time and date handling routines.

Authors
  • Michael R. Elkins

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file date.c.

Function Documentation

◆ compute_tz()

static time_t compute_tz ( time_t  g,
struct tm *  utc 
)
static

Calculate the number of seconds east of UTC.

Parameters
gLocal time
utcUTC time
Return values
numSeconds east of UTC

returns the seconds east of UTC given 'g' and its corresponding gmtime() representation

Definition at line 125 of file date.c.

126 {
127  struct tm lt = mutt_date_localtime(g);
128 
129  time_t t = (((lt.tm_hour - utc->tm_hour) * 60) + (lt.tm_min - utc->tm_min)) * 60;
130 
131  int yday = (lt.tm_yday - utc->tm_yday);
132  if (yday != 0)
133  {
134  /* This code is optimized to negative timezones (West of Greenwich) */
135  if ((yday == -1) || /* UTC passed midnight before localtime */
136  (yday > 1)) /* UTC passed new year before localtime */
137  {
138  t -= (24 * 60 * 60);
139  }
140  else
141  {
142  t += (24 * 60 * 60);
143  }
144  }
145 
146  return t;
147 }
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:737
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ is_leap_year_feb()

static int is_leap_year_feb ( struct tm *  tm)
static

Is a given February in a leap year.

Parameters
tmDate to be tested
Return values
trueif it's a leap year

Definition at line 154 of file date.c.

155 {
156  if (tm->tm_mon != 1)
157  return 0;
158 
159  int y = tm->tm_year + 1900;
160  return ((y & 3) == 0) && (((y % 100) != 0) || ((y % 400) == 0));
161 }
+ Here is the caller graph for this function:

◆ uncomment_timezone()

static const char* uncomment_timezone ( char *  buf,
size_t  buflen,
const char *  tz 
)
static

Strip ()s from a timezone string.

Parameters
bufBuffer to store the results
buflenLength of buffer
tzTimezone string to copy
Return values
ptrResults buffer

Some time formats have the timezone in ()s, e.g. (MST) or (-0700)

Note
If the timezone doesn't have any ()s the function will return a pointer to the original string.

Definition at line 175 of file date.c.

176 {
177  char *p = NULL;
178  size_t len;
179 
180  if (*tz != '(')
181  return tz; /* no need to do anything */
182  tz = mutt_str_skip_email_wsp(tz + 1);
183  p = strpbrk(tz, " )");
184  if (!p)
185  return tz;
186  len = p - tz;
187  if (len > (buflen - 1))
188  len = buflen - 1; /* LCOV_EXCL_LINE */
189  memcpy(buf, tz, len);
190  buf[len] = '\0';
191  return buf;
192 }
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:776
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_local_tz()

time_t mutt_date_local_tz ( time_t  t)

Calculate the local timezone in seconds east of UTC.

Parameters
tTime to examine
Return values
numSeconds east of UTC

Returns the local timezone in seconds east of UTC for the time t, or for the current time if t is zero.

Definition at line 202 of file date.c.

203 {
204  /* Check we haven't overflowed the time (on 32-bit arches) */
205  if ((t == TIME_T_MAX) || (t == TIME_T_MIN))
206  return 0;
207 
208  if (t == 0)
209  t = mutt_date_epoch();
210 
211  struct tm tm = mutt_date_gmtime(t);
212  return compute_tz(t, &tm);
213 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:411
#define TIME_T_MIN
Definition: date.h:32
#define TIME_T_MAX
Definition: date.h:31
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone. ...
Definition: date.c:755
static time_t compute_tz(time_t g, struct tm *utc)
Calculate the number of seconds east of UTC.
Definition: date.c:125
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_make_time()

time_t mutt_date_make_time ( struct tm *  t,
bool  local 
)

Convert struct tm to time_t

Parameters
tTime to convert
localShould the local timezone be considered
Return values
numTime in Unix format
TIME_T_MINError

Convert a struct tm to time_t, but don't take the local timezone into account unless "local" is nonzero

Definition at line 225 of file date.c.

226 {
227  if (!t)
228  return TIME_T_MIN;
229 
230  static const int AccumDaysPerMonth[mutt_array_size(Months)] = {
231  0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
232  };
233 
234  /* Prevent an integer overflow, with some arbitrary limits. */
235  if (t->tm_year > 10000)
236  return TIME_T_MAX;
237  if (t->tm_year < -10000)
238  return TIME_T_MIN;
239 
240  if ((t->tm_mday < 1) || (t->tm_mday > 31))
241  return TIME_T_MIN;
242  if ((t->tm_hour < 0) || (t->tm_hour > 23) || (t->tm_min < 0) ||
243  (t->tm_min > 59) || (t->tm_sec < 0) || (t->tm_sec > 60))
244  {
245  return TIME_T_MIN;
246  }
247  if (t->tm_year > 9999)
248  return TIME_T_MAX;
249 
250  /* Compute the number of days since January 1 in the same year */
251  time_t g = AccumDaysPerMonth[t->tm_mon % mutt_array_size(Months)];
252 
253  /* The leap years are 1972 and every 4. year until 2096,
254  * but this algorithm will fail after year 2099 */
255  g += t->tm_mday;
256  if ((t->tm_year % 4) || (t->tm_mon < 2))
257  g--;
258  t->tm_yday = g;
259 
260  /* Compute the number of days since January 1, 1970 */
261  g += (t->tm_year - 70) * (time_t) 365;
262  g += (t->tm_year - 69) / 4;
263 
264  /* Compute the number of hours */
265  g *= 24;
266  g += t->tm_hour;
267 
268  /* Compute the number of minutes */
269  g *= 60;
270  g += t->tm_min;
271 
272  /* Compute the number of seconds */
273  g *= 60;
274  g += t->tm_sec;
275 
276  if (local)
277  g -= compute_tz(g, t);
278 
279  return g;
280 }
#define TIME_T_MIN
Definition: date.h:32
#define TIME_T_MAX
Definition: date.h:31
static const char *const Months[]
Months of the year (abbreviated)
Definition: date.c:54
#define mutt_array_size(x)
Definition: memory.h:33
static time_t compute_tz(time_t g, struct tm *utc)
Calculate the number of seconds east of UTC.
Definition: date.c:125
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_normalize_time()

void mutt_date_normalize_time ( struct tm *  tm)

Fix the contents of a struct tm.

Parameters
tmTime to correct

If values have been added/subtracted from a struct tm, it can lead to invalid dates, e.g. Adding 10 days to the 25th of a month.

This function will correct any over/under-flow.

Definition at line 291 of file date.c.

292 {
293  if (!tm)
294  return;
295 
296  static const char DaysPerMonth[mutt_array_size(Months)] = {
297  31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
298  };
299  int leap;
300 
301  while (tm->tm_sec < 0)
302  {
303  tm->tm_sec += 60;
304  tm->tm_min--;
305  }
306  while (tm->tm_sec >= 60)
307  {
308  tm->tm_sec -= 60;
309  tm->tm_min++;
310  }
311  while (tm->tm_min < 0)
312  {
313  tm->tm_min += 60;
314  tm->tm_hour--;
315  }
316  while (tm->tm_min >= 60)
317  {
318  tm->tm_min -= 60;
319  tm->tm_hour++;
320  }
321  while (tm->tm_hour < 0)
322  {
323  tm->tm_hour += 24;
324  tm->tm_mday--;
325  }
326  while (tm->tm_hour >= 24)
327  {
328  tm->tm_hour -= 24;
329  tm->tm_mday++;
330  }
331  /* use loops on NNNdwmy user input values? */
332  while (tm->tm_mon < 0)
333  {
334  tm->tm_mon += 12;
335  tm->tm_year--;
336  }
337  while (tm->tm_mon >= 12)
338  {
339  tm->tm_mon -= 12;
340  tm->tm_year++;
341  }
342  while (tm->tm_mday <= 0)
343  {
344  if (tm->tm_mon)
345  tm->tm_mon--;
346  else
347  {
348  tm->tm_mon = 11;
349  tm->tm_year--;
350  }
351  tm->tm_mday += DaysPerMonth[tm->tm_mon] + is_leap_year_feb(tm);
352  }
353  while (tm->tm_mday > (DaysPerMonth[tm->tm_mon] + (leap = is_leap_year_feb(tm))))
354  {
355  tm->tm_mday -= DaysPerMonth[tm->tm_mon] + leap;
356  if (tm->tm_mon < 11)
357  tm->tm_mon++;
358  else
359  {
360  tm->tm_mon = 0;
361  tm->tm_year++;
362  }
363  }
364 }
static const char *const Months[]
Months of the year (abbreviated)
Definition: date.c:54
static int is_leap_year_feb(struct tm *tm)
Is a given February in a leap year.
Definition: date.c:154
#define mutt_array_size(x)
Definition: memory.h:33
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_make_date()

char* mutt_date_make_date ( char *  buf,
size_t  buflen 
)

Write a date in RFC822 format to a buffer.

Parameters
bufBuffer for result
buflenLength of buffer
Return values
ptrBuffer containing result

Definition at line 372 of file date.c.

373 {
374  if (!buf)
375  return NULL;
376 
377  time_t t = mutt_date_epoch();
378  struct tm tm = mutt_date_localtime(t);
379  time_t tz = mutt_date_local_tz(t);
380 
381  tz /= 60;
382 
383  snprintf(buf, buflen, "Date: %s, %d %s %d %02d:%02d:%02d %+03d%02d\n",
384  Weekdays[tm.tm_wday], tm.tm_mday, Months[tm.tm_mon], tm.tm_year + 1900,
385  tm.tm_hour, tm.tm_min, tm.tm_sec, (int) tz / 60, (int) abs((int) tz) % 60);
386  return buf;
387 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:411
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:737
static const char *const Months[]
Months of the year (abbreviated)
Definition: date.c:54
time_t mutt_date_local_tz(time_t t)
Calculate the local timezone in seconds east of UTC.
Definition: date.c:202
static const char *const Weekdays[]
Day of the week (abbreviated)
Definition: date.c:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_check_month()

int mutt_date_check_month ( const char *  s)

Is the string a valid month name.

Parameters
sString to check
Return values
numIndex into Months array (0-based)
-1Error
Note
Only the first three characters are checked
The comparison is case insensitive

Definition at line 398 of file date.c.

399 {
400  for (int i = 0; i < mutt_array_size(Months); i++)
402  return i;
403 
404  return -1; /* error */
405 }
static const char *const Months[]
Months of the year (abbreviated)
Definition: date.c:54
#define mutt_array_size(x)
Definition: memory.h:33
Ignore case when comparing strings.
Definition: string2.h:68
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_epoch()

time_t mutt_date_epoch ( void  )

Return the number of seconds since the Unix epoch.

Return values
sThe number of s since the Unix epoch, or 0 on failure

Definition at line 411 of file date.c.

412 {
413  return mutt_date_epoch_ms() / 1000;
414 }
uint64_t mutt_date_epoch_ms(void)
Return the number of milliseconds since the Unix epoch.
Definition: date.c:420
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_epoch_ms()

uint64_t mutt_date_epoch_ms ( void  )

Return the number of milliseconds since the Unix epoch.

Return values
msThe number of ms since the Unix epoch, or 0 on failure

Definition at line 420 of file date.c.

421 {
422  struct timeval tv = { 0, 0 };
423  gettimeofday(&tv, NULL);
424  /* We assume that gettimeofday doesn't modify its first argument on failure.
425  * We also kind of assume that gettimeofday does not fail. */
426  return (uint64_t) tv.tv_sec * 1000 + tv.tv_usec / 1000;
427 }
+ Here is the caller graph for this function:

◆ mutt_date_is_day_name()

bool mutt_date_is_day_name ( const char *  s)

Is the string a valid day name.

Parameters
sString to check
Return values
trueIt's a valid day name
Note
Only the first three characters are checked
The comparison is case insensitive

Definition at line 437 of file date.c.

438 {
439  if (!s || (strlen(s) < 3) || (s[3] == '\0') || !IS_SPACE(s[3]))
440  return false;
441 
442  for (int i = 0; i < mutt_array_size(Weekdays); i++)
444  return true;
445 
446  return false;
447 }
#define mutt_array_size(x)
Definition: memory.h:33
Ignore case when comparing strings.
Definition: string2.h:68
size_t mutt_str_startswith(const char *str, const char *prefix, enum CaseSensitivity cs)
Check whether a string starts with a prefix.
Definition: string.c:168
#define IS_SPACE(ch)
Definition: string2.h:38
static const char *const Weekdays[]
Day of the week (abbreviated)
Definition: date.c:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_parse_date()

time_t mutt_date_parse_date ( const char *  s,
struct Tz tz_out 
)

Parse a date string in RFC822 format.

Parameters
[in]sString to parse
[out]tz_outPointer to timezone (optional)
Return values
numUnix time in seconds

Parse a date of the form: [ weekday , ] day-of-month month year hour:minute:second [ timezone ]

The 'timezone' field is optional; it defaults to +0000 if missing.

Definition at line 460 of file date.c.

461 {
462  if (!s)
463  return -1;
464 
465  int count = 0;
466  int hour, min, sec;
467  struct tm tm = { 0 };
468  int i;
469  int tz_offset = 0;
470  int zhours = 0;
471  int zminutes = 0;
472  bool zoccident = false;
473  const char *ptz = NULL;
474  char tzstr[128];
475  char scratch[128];
476 
477  /* Don't modify our argument. Fixed-size buffer is ok here since
478  * the date format imposes a natural limit. */
479 
480  mutt_str_strfcpy(scratch, s, sizeof(scratch));
481 
482  /* kill the day of the week, if it exists. */
483  char *t = strchr(scratch, ',');
484  if (t)
485  t++;
486  else
487  t = scratch;
489 
490  while ((t = strtok(t, " \t")))
491  {
492  switch (count)
493  {
494  case 0: /* day of the month */
495  if ((mutt_str_atoi(t, &tm.tm_mday) < 0) || (tm.tm_mday < 0))
496  return -1;
497  if (tm.tm_mday > 31)
498  return -1;
499  break;
500 
501  case 1: /* month of the year */
502  i = mutt_date_check_month(t);
503  if ((i < 0) || (i > 11))
504  return -1;
505  tm.tm_mon = i;
506  break;
507 
508  case 2: /* year */
509  if ((mutt_str_atoi(t, &tm.tm_year) < 0) || (tm.tm_year < 0))
510  return -1;
511  if ((tm.tm_year < 0) || (tm.tm_year > 9999))
512  return -1;
513  if (tm.tm_year < 50)
514  tm.tm_year += 100;
515  else if (tm.tm_year >= 1900)
516  tm.tm_year -= 1900;
517  break;
518 
519  case 3: /* time of day */
520  if (sscanf(t, "%d:%d:%d", &hour, &min, &sec) == 3)
521  ;
522  else if (sscanf(t, "%d:%d", &hour, &min) == 2)
523  sec = 0;
524  else
525  {
526  mutt_debug(LL_DEBUG1, "could not process time format: %s\n", t);
527  return -1;
528  }
529  if ((hour < 0) || (hour > 23) || (min < 0) || (min > 59) || (sec < 0) || (sec > 60))
530  return -1;
531  tm.tm_hour = hour;
532  tm.tm_min = min;
533  tm.tm_sec = sec;
534  break;
535 
536  case 4: /* timezone */
537  /* sometimes we see things like (MST) or (-0700) so attempt to
538  * compensate by uncommenting the string if non-RFC822 compliant */
539  ptz = uncomment_timezone(tzstr, sizeof(tzstr), t);
540 
541  if ((*ptz == '+') || (*ptz == '-'))
542  {
543  if ((ptz[1] != '\0') && (ptz[2] != '\0') && (ptz[3] != '\0') && (ptz[4] != '\0') &&
544  isdigit((unsigned char) ptz[1]) && isdigit((unsigned char) ptz[2]) &&
545  isdigit((unsigned char) ptz[3]) && isdigit((unsigned char) ptz[4]))
546  {
547  zhours = (ptz[1] - '0') * 10 + (ptz[2] - '0');
548  zminutes = (ptz[3] - '0') * 10 + (ptz[4] - '0');
549 
550  if (ptz[0] == '-')
551  zoccident = true;
552  }
553  }
554  else
555  {
556  /* This is safe to do: A pointer to a struct equals a pointer to its first element */
557  struct Tz *tz =
558  bsearch(ptz, TimeZones, mutt_array_size(TimeZones), sizeof(struct Tz),
559  (int (*)(const void *, const void *)) mutt_str_strcasecmp);
560 
561  if (tz)
562  {
563  zhours = tz->zhours;
564  zminutes = tz->zminutes;
565  zoccident = tz->zoccident;
566  }
567 
568  /* ad hoc support for the European MET (now officially CET) TZ */
569  if (mutt_str_strcasecmp(t, "MET") == 0)
570  {
571  t = strtok(NULL, " \t");
572  if (t)
573  {
574  if (mutt_str_strcasecmp(t, "DST") == 0)
575  zhours++;
576  }
577  }
578  }
579  tz_offset = (zhours * 3600) + (zminutes * 60);
580  if (!zoccident)
581  tz_offset = -tz_offset;
582  break;
583  }
584  count++;
585  t = 0;
586  }
587 
588  if (count < 4) /* don't check for missing timezone */
589  {
590  mutt_debug(LL_DEBUG1, "error parsing date format, using received time\n");
591  return -1;
592  }
593 
594  if (tz_out)
595  {
596  tz_out->zhours = zhours;
597  tz_out->zminutes = zminutes;
598  tz_out->zoccident = zoccident;
599  }
600 
601  time_t time = mutt_date_make_time(&tm, false);
602  /* Check we haven't overflowed the time (on 32-bit arches) */
603  if ((time != TIME_T_MAX) && (time != TIME_T_MIN))
604  time += tz_offset;
605 
606  return time;
607 }
#define TIME_T_MIN
Definition: date.h:32
int mutt_str_atoi(const char *str, int *dst)
Convert ASCII string to an integer.
Definition: string.c:262
#define TIME_T_MAX
Definition: date.h:31
unsigned char zhours
Hours away from UTC.
Definition: date.h:45
#define mutt_array_size(x)
Definition: memory.h:33
bool zoccident
True if west of UTC, False if East.
Definition: date.h:47
size_t mutt_str_strfcpy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:750
char * mutt_str_skip_email_wsp(const char *s)
Skip over whitespace as defined by RFC5322.
Definition: string.c:776
unsigned char zminutes
Minutes away from UTC.
Definition: date.h:46
List of recognised Timezones.
Definition: date.h:42
Log at debug level 1.
Definition: logging.h:40
static const char * uncomment_timezone(char *buf, size_t buflen, const char *tz)
Strip ()s from a timezone string.
Definition: date.c:175
static const struct Tz TimeZones[]
Lookup table of Time Zones.
Definition: date.c:64
int mutt_str_strcasecmp(const char *a, const char *b)
Compare two strings ignoring case, safely.
Definition: string.c:628
int mutt_date_check_month(const char *s)
Is the string a valid month name.
Definition: date.c:398
#define mutt_debug(LEVEL,...)
Definition: logging.h:81
time_t mutt_date_make_time(struct tm *t, bool local)
Convert struct tm to time_t
Definition: date.c:225
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_make_imap()

int mutt_date_make_imap ( char *  buf,
size_t  buflen,
time_t  timestamp 
)

Format date in IMAP style: DD-MMM-YYYY HH:MM:SS +ZZzz.

Parameters
bufBuffer to store the results
buflenLength of buffer
timestampTime to format
Return values
numCharacters written to buf

Caller should provide a buffer of at least 27 bytes.

Definition at line 618 of file date.c.

619 {
620  if (!buf)
621  return -1;
622 
623  struct tm tm = mutt_date_localtime(timestamp);
624  time_t tz = mutt_date_local_tz(timestamp);
625 
626  tz /= 60;
627 
628  return snprintf(buf, buflen, "%02d-%s-%d %02d:%02d:%02d %+03d%02d",
629  tm.tm_mday, Months[tm.tm_mon], tm.tm_year + 1900, tm.tm_hour,
630  tm.tm_min, tm.tm_sec, (int) tz / 60, (int) abs((int) tz) % 60);
631 }
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:737
static const char *const Months[]
Months of the year (abbreviated)
Definition: date.c:54
static const char * timestamp(time_t stamp)
Create a YYYY-MM-DD HH:MM:SS timestamp.
Definition: logging.c:77
time_t mutt_date_local_tz(time_t t)
Calculate the local timezone in seconds east of UTC.
Definition: date.c:202
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_make_tls()

int mutt_date_make_tls ( char *  buf,
size_t  buflen,
time_t  timestamp 
)

Format date in TLS certificate verification style.

Parameters
bufBuffer to store the results
buflenLength of buffer
timestampTime to format
Return values
numCharacters written to buf

e.g., Mar 17 16:40:46 2016 UTC. The time is always in UTC.

Caller should provide a buffer of at least 27 bytes.

Definition at line 644 of file date.c.

645 {
646  if (!buf)
647  return -1;
648 
649  struct tm tm = mutt_date_gmtime(timestamp);
650  return snprintf(buf, buflen, "%s, %d %s %d %02d:%02d:%02d UTC",
651  Weekdays[tm.tm_wday], tm.tm_mday, Months[tm.tm_mon],
652  tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
653 }
static const char *const Months[]
Months of the year (abbreviated)
Definition: date.c:54
static const char * timestamp(time_t stamp)
Create a YYYY-MM-DD HH:MM:SS timestamp.
Definition: logging.c:77
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone. ...
Definition: date.c:755
static const char *const Weekdays[]
Day of the week (abbreviated)
Definition: date.c:47
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_parse_imap()

time_t mutt_date_parse_imap ( const char *  s)

Parse date of the form: DD-MMM-YYYY HH:MM:SS +ZZzz.

Parameters
sDate in string form
Return values
numUnix time
0Error

Definition at line 661 of file date.c.

662 {
663  if (!s)
664  return 0;
665 
666  struct tm t;
667  time_t tz;
668 
669  t.tm_mday = ((s[0] == ' ') ? s[1] - '0' : (s[0] - '0') * 10 + (s[1] - '0'));
670  s += 2;
671  if (*s != '-')
672  return 0;
673  s++;
674  t.tm_mon = mutt_date_check_month(s);
675  s += 3;
676  if (*s != '-')
677  return 0;
678  s++;
679  t.tm_year = (s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 +
680  (s[3] - '0') - 1900;
681  s += 4;
682  if (*s != ' ')
683  return 0;
684  s++;
685 
686  /* time */
687  t.tm_hour = (s[0] - '0') * 10 + (s[1] - '0');
688  s += 2;
689  if (*s != ':')
690  return 0;
691  s++;
692  t.tm_min = (s[0] - '0') * 10 + (s[1] - '0');
693  s += 2;
694  if (*s != ':')
695  return 0;
696  s++;
697  t.tm_sec = (s[0] - '0') * 10 + (s[1] - '0');
698  s += 2;
699  if (*s != ' ')
700  return 0;
701  s++;
702 
703  /* timezone */
704  tz = ((s[1] - '0') * 10 + (s[2] - '0')) * 3600 + ((s[3] - '0') * 10 + (s[4] - '0')) * 60;
705  if (s[0] == '+')
706  tz = -tz;
707 
708  return mutt_date_make_time(&t, false) + tz;
709 }
int mutt_date_check_month(const char *s)
Is the string a valid month name.
Definition: date.c:398
time_t mutt_date_make_time(struct tm *t, bool local)
Convert struct tm to time_t
Definition: date.c:225
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_add_timeout()

time_t mutt_date_add_timeout ( time_t  now,
long  timeout 
)

Safely add a timeout to a given time_t value.

Parameters
nowTime now
timeoutTimeout in seconds
Return values
numUnix time to timeout

This will truncate instead of overflowing.

Definition at line 719 of file date.c.

720 {
721  if (timeout < 0)
722  return now;
723 
724  if ((TIME_T_MAX - now) < timeout)
725  return TIME_T_MAX;
726 
727  return now + timeout;
728 }
#define TIME_T_MAX
Definition: date.h:31
+ Here is the caller graph for this function:

◆ mutt_date_localtime()

struct tm mutt_date_localtime ( time_t  t)

Converts calendar time to a broken-down time structure expressed in user timezone.

Parameters
tTime
Return values
objBroken-down time representation

Uses current time if t is MUTT_DATE_NOW

Definition at line 737 of file date.c.

738 {
739  struct tm tm = { 0 };
740 
741  if (t == MUTT_DATE_NOW)
742  t = mutt_date_epoch();
743 
744  localtime_r(&t, &tm);
745  return tm;
746 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:411
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_gmtime()

struct tm mutt_date_gmtime ( time_t  t)

Converts calendar time to a broken-down time structure expressed in UTC timezone.

Parameters
tTime
Return values
objBroken-down time representation

Uses current time if t is MUTT_DATE_NOW

Definition at line 755 of file date.c.

756 {
757  struct tm tm = { 0 };
758 
759  if (t == MUTT_DATE_NOW)
760  t = mutt_date_epoch();
761 
762  gmtime_r(&t, &tm);
763  return tm;
764 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:411
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:37
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_localtime_format()

size_t mutt_date_localtime_format ( char *  buf,
size_t  buflen,
const char *  format,
time_t  t 
)

Format localtime.

Parameters
bufBuffer to store formatted time
buflenBuffer size
formatFormat to apply
tTime to format
Return values
numNumber of Bytes added to buffer, excluding null byte.

Definition at line 774 of file date.c.

775 {
776  if (!buf || !format)
777  return 0;
778 
779  struct tm tm = mutt_date_localtime(t);
780  return strftime(buf, buflen, format, &tm);
781 }
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:737
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_date_sleep_ms()

void mutt_date_sleep_ms ( size_t  ms)

Sleep for milliseconds.

Parameters
msNumber of milliseconds to sleep

Definition at line 787 of file date.c.

788 {
789  const struct timespec sleep = {
790  .tv_sec = ms / 1000,
791  .tv_nsec = (ms % 1000) * 1000000UL,
792  };
793  nanosleep(&sleep, NULL);
794 }
time_t tv_sec
Definition: file.h:47
Time value with nanosecond precision.
Definition: file.h:45
+ Here is the caller graph for this function:

Variable Documentation

◆ Weekdays

const char* const Weekdays[]
static
Initial value:
= {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
}

Day of the week (abbreviated)

Definition at line 47 of file date.c.

◆ Months

const char* const Months[]
static
Initial value:
= {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
}

Months of the year (abbreviated)

Definition at line 54 of file date.c.

◆ TimeZones

const struct Tz TimeZones[]
static

Lookup table of Time Zones.

Note
Keep in alphabetical order

Definition at line 64 of file date.c.