NeoMutt  2019-11-11
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 <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...
 
size_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 124 of file date.c.

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

154 {
155  if (tm->tm_mon != 1)
156  return 0;
157 
158  int y = tm->tm_year + 1900;
159  return ((y & 3) == 0) && (((y % 100) != 0) || ((y % 400) == 0));
160 }
+ 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 174 of file date.c.

175 {
176  char *p = NULL;
177  size_t len;
178 
179  if (*tz != '(')
180  return tz; /* no need to do anything */
181  tz = mutt_str_skip_email_wsp(tz + 1);
182  p = strpbrk(tz, " )");
183  if (!p)
184  return tz;
185  len = p - tz;
186  if (len > (buflen - 1))
187  len = buflen - 1; /* LCOV_EXCL_LINE */
188  memcpy(buf, tz, len);
189  buf[len] = '\0';
190  return buf;
191 }
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 201 of file date.c.

202 {
203  /* Check we haven't overflowed the time (on 32-bit arches) */
204  if ((t == TIME_T_MAX) || (t == TIME_T_MIN))
205  return 0;
206 
207  if (t == 0)
208  t = mutt_date_epoch();
209 
210  struct tm tm = mutt_date_gmtime(t);
211  return compute_tz(t, &tm);
212 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:410
#define TIME_T_MIN
Definition: date.h:31
#define TIME_T_MAX
Definition: date.h:30
struct tm mutt_date_gmtime(time_t t)
Converts calendar time to a broken-down time structure expressed in UTC timezone. ...
Definition: date.c:754
static time_t compute_tz(time_t g, struct tm *utc)
Calculate the number of seconds east of UTC.
Definition: date.c:124
+ 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 224 of file date.c.

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

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

372 {
373  if (!buf)
374  return NULL;
375 
376  time_t t = mutt_date_epoch();
377  struct tm tm = mutt_date_localtime(t);
378  time_t tz = mutt_date_local_tz(t);
379 
380  tz /= 60;
381 
382  snprintf(buf, buflen, "Date: %s, %d %s %d %02d:%02d:%02d %+03d%02d\n",
383  Weekdays[tm.tm_wday], tm.tm_mday, Months[tm.tm_mon], tm.tm_year + 1900,
384  tm.tm_hour, tm.tm_min, tm.tm_sec, (int) tz / 60, (int) abs((int) tz) % 60);
385  return buf;
386 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:410
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:736
static const char *const Months[]
Months of the year (abbreviated)
Definition: date.c:53
time_t mutt_date_local_tz(time_t t)
Calculate the local timezone in seconds east of UTC.
Definition: date.c:201
static const char *const Weekdays[]
Day of the week (abbreviated)
Definition: date.c:46
+ 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 397 of file date.c.

398 {
399  for (int i = 0; i < mutt_array_size(Months); i++)
401  return i;
402 
403  return -1; /* error */
404 }
static const char *const Months[]
Months of the year (abbreviated)
Definition: date.c:53
#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 410 of file date.c.

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

◆ mutt_date_epoch_ms()

size_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 419 of file date.c.

420 {
421  struct timeval tv = { 0, 0 };
422  gettimeofday(&tv, NULL);
423  /* We assume that gettimeofday doesn't modify its first argument on failure.
424  * We also kind of assume that gettimeofday does not fail. */
425  return tv.tv_sec * 1000 + tv.tv_usec / 1000;
426 }
+ 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 436 of file date.c.

437 {
438  if (!s || (strlen(s) < 3) || (s[3] == '\0') || !IS_SPACE(s[3]))
439  return false;
440 
441  for (int i = 0; i < mutt_array_size(Weekdays); i++)
443  return true;
444 
445  return false;
446 }
#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:46
+ 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 459 of file date.c.

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

618 {
619  if (!buf)
620  return -1;
621 
622  struct tm tm = mutt_date_localtime(timestamp);
623  time_t tz = mutt_date_local_tz(timestamp);
624 
625  tz /= 60;
626 
627  return snprintf(buf, buflen, "%02d-%s-%d %02d:%02d:%02d %+03d%02d",
628  tm.tm_mday, Months[tm.tm_mon], tm.tm_year + 1900, tm.tm_hour,
629  tm.tm_min, tm.tm_sec, (int) tz / 60, (int) abs((int) tz) % 60);
630 }
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:736
static const char *const Months[]
Months of the year (abbreviated)
Definition: date.c:53
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:201
+ 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 643 of file date.c.

644 {
645  if (!buf)
646  return -1;
647 
648  struct tm tm = mutt_date_gmtime(timestamp);
649  return snprintf(buf, buflen, "%s, %d %s %d %02d:%02d:%02d UTC",
650  Weekdays[tm.tm_wday], tm.tm_mday, Months[tm.tm_mon],
651  tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
652 }
static const char *const Months[]
Months of the year (abbreviated)
Definition: date.c:53
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:754
static const char *const Weekdays[]
Day of the week (abbreviated)
Definition: date.c:46
+ 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 660 of file date.c.

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

719 {
720  if (timeout < 0)
721  return now;
722 
723  if ((TIME_T_MAX - now) < timeout)
724  return TIME_T_MAX;
725 
726  return now + timeout;
727 }
#define TIME_T_MAX
Definition: date.h:30
+ 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 736 of file date.c.

737 {
738  struct tm tm = { 0 };
739 
740  if (t == MUTT_DATE_NOW)
741  t = mutt_date_epoch();
742 
743  localtime_r(&t, &tm);
744  return tm;
745 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:410
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:36
+ 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 754 of file date.c.

755 {
756  struct tm tm = { 0 };
757 
758  if (t == MUTT_DATE_NOW)
759  t = mutt_date_epoch();
760 
761  gmtime_r(&t, &tm);
762  return tm;
763 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:410
#define MUTT_DATE_NOW
Constant representing the &#39;current time&#39;, see: mutt_date_gmtime(), mutt_date_localtime() ...
Definition: date.h:36
+ 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 773 of file date.c.

774 {
775  if (!buf || !format)
776  return 0;
777 
778  struct tm tm = mutt_date_localtime(t);
779  return strftime(buf, buflen, format, &tm);
780 }
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:736
+ 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 786 of file date.c.

787 {
788  const struct timespec sleep = {
789  .tv_sec = ms / 1000,
790  .tv_nsec = (ms % 1000) * 1000000UL,
791  };
792  nanosleep(&sleep, NULL);
793 }
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 46 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 53 of file date.c.

◆ TimeZones

const struct Tz TimeZones[]
static

Lookup table of Time Zones.

Note
Keep in alphabetical order

Definition at line 63 of file date.c.