NeoMutt  2020-06-26-89-g172cd3
Teaching an old dog new tricks
DOXYGEN
date.c File Reference

Time and date handling routines. More...

#include "config.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <time.h>
#include "date.h"
#include "logging.h"
#include "memory.h"
#include "prex.h"
#include "regex3.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 time_t add_tz_offset (time_t t, bool w, time_t h, time_t m)
 Compute and add a timezone offset to an UTC time. More...
 
static const struct Tzfind_tz (const char *s, size_t len)
 Look up a timezone. More...
 
static int is_leap_year_feb (struct tm *tm)
 Is a given February in a leap year. 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...
 
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, time_t 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 126 of file date.c.

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

◆ add_tz_offset()

static time_t add_tz_offset ( time_t  t,
bool  w,
time_t  h,
time_t  m 
)
static

Compute and add a timezone offset to an UTC time.

Parameters
tUTC time
wTrue if west of UTC, false if east
hNumber of hours in the timezone
mNumber of minutes in the timezone
Return values
Timezoneoffset in seconds

Definition at line 158 of file date.c.

159 {
160  if ((t != TIME_T_MAX) && (t != TIME_T_MIN))
161  return t + (w ? 1 : -1) * (((time_t) h * 3600) + ((time_t) m * 60));
162  else
163  return t;
164 }
#define TIME_T_MIN
Definition: date.h:32
#define TIME_T_MAX
Definition: date.h:31
+ Here is the caller graph for this function:

◆ find_tz()

static const struct Tz* find_tz ( const char *  s,
size_t  len 
)
static

Look up a timezone.

Parameters
sTimezone to lookup
lenLength of the s string
Return values
ptrPointer to the Tz struct
NULLNot found

Definition at line 173 of file date.c.

174 {
175  for (size_t i = 0; i < mutt_array_size(TimeZones); i++)
176  {
177  if (mutt_istrn_equal(TimeZones[i].tzname, s, len))
178  return &TimeZones[i];
179  }
180  return NULL;
181 }
bool mutt_istrn_equal(const char *a, const char *b, size_t l)
Check for equality of two strings ignoring case (to a maximum), safely.
Definition: string.c:626
#define mutt_array_size(x)
Definition: memory.h:33
static const struct Tz TimeZones[]
Lookup table of Time Zones.
Definition: date.c:64
+ 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 188 of file date.c.

189 {
190  if (tm->tm_mon != 1)
191  return 0;
192 
193  int y = tm->tm_year + 1900;
194  return ((y & 3) == 0) && (((y % 100) != 0) || ((y % 400) == 0));
195 }
+ 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 205 of file date.c.

206 {
207  /* Check we haven't overflowed the time (on 32-bit arches) */
208  if ((t == TIME_T_MAX) || (t == TIME_T_MIN))
209  return 0;
210 
211  if (t == 0)
212  t = mutt_date_epoch();
213 
214  struct tm tm = mutt_date_gmtime(t);
215  return compute_tz(t, &tm);
216 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:414
#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:659
static time_t compute_tz(time_t g, struct tm *utc)
Calculate the number of seconds east of UTC.
Definition: date.c:126
+ 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 228 of file date.c.

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

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

376 {
377  if (!buf)
378  return NULL;
379 
380  time_t t = mutt_date_epoch();
381  struct tm tm = mutt_date_localtime(t);
382  time_t tz = mutt_date_local_tz(t);
383 
384  tz /= 60;
385 
386  snprintf(buf, buflen, "Date: %s, %d %s %d %02d:%02d:%02d %+03d%02d\n",
387  Weekdays[tm.tm_wday], tm.tm_mday, Months[tm.tm_mon], tm.tm_year + 1900,
388  tm.tm_hour, tm.tm_min, tm.tm_sec, (int) tz / 60, (int) abs((int) tz) % 60);
389  return buf;
390 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:414
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:641
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:205
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 401 of file date.c.

402 {
403  for (int i = 0; i < mutt_array_size(Months); i++)
404  if (mutt_istr_startswith(s, Months[i]))
405  return i;
406 
407  return -1; /* error */
408 }
static const char *const Months[]
Months of the year (abbreviated)
Definition: date.c:54
#define mutt_array_size(x)
Definition: memory.h:33
size_t mutt_istr_startswith(const char *str, const char *prefix)
Check whether a string starts with a prefix, ignoring case.
Definition: string.c:177
+ 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 414 of file date.c.

415 {
416  return mutt_date_epoch_ms() / 1000;
417 }
uint64_t mutt_date_epoch_ms(void)
Return the number of milliseconds since the Unix epoch.
Definition: date.c:423
+ 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 423 of file date.c.

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

444 {
445  if (!s)
446  return -1;
447 
448  bool lax = false;
449 
450  const regmatch_t *match = mutt_prex_capture(PREX_RFC5322_DATE, s);
451  if (!match)
452  {
454  if (!match)
455  {
456  mutt_debug(LL_DEBUG1, "Could not parse date: <%s>\n", s);
457  return -1;
458  }
459  lax = true;
460  mutt_debug(LL_DEBUG2, "Fallback regex for date: <%s>\n", s);
461  }
462 
463  struct tm tm = { 0 };
464 
465  // clang-format off
466  const regmatch_t *mday = &match[lax ? PREX_RFC5322_DATE_LAX_MATCH_DAY : PREX_RFC5322_DATE_MATCH_DAY];
467  const regmatch_t *mmonth = &match[lax ? PREX_RFC5322_DATE_LAX_MATCH_MONTH : PREX_RFC5322_DATE_MATCH_MONTH];
468  const regmatch_t *myear = &match[lax ? PREX_RFC5322_DATE_LAX_MATCH_YEAR : PREX_RFC5322_DATE_MATCH_YEAR];
469  const regmatch_t *mhour = &match[lax ? PREX_RFC5322_DATE_LAX_MATCH_HOUR : PREX_RFC5322_DATE_MATCH_HOUR];
470  const regmatch_t *mminute = &match[lax ? PREX_RFC5322_DATE_LAX_MATCH_MINUTE : PREX_RFC5322_DATE_MATCH_MINUTE];
471  const regmatch_t *msecond = &match[lax ? PREX_RFC5322_DATE_LAX_MATCH_SECOND : PREX_RFC5322_DATE_MATCH_SECOND];
472  const regmatch_t *mtz = &match[lax ? PREX_RFC5322_DATE_LAX_MATCH_TZ : PREX_RFC5322_DATE_MATCH_TZ];
473  const regmatch_t *mtzobs = &match[lax ? PREX_RFC5322_DATE_LAX_MATCH_TZ_OBS : PREX_RFC5322_DATE_MATCH_TZ_OBS];
474  // clang-format on
475 
476  /* Day */
477  sscanf(s + mutt_regmatch_start(mday), "%d", &tm.tm_mday);
478  if (tm.tm_mday > 31)
479  return -1;
480 
481  /* Month */
482  tm.tm_mon = mutt_date_check_month(s + mutt_regmatch_start(mmonth));
483 
484  /* Year */
485  sscanf(s + mutt_regmatch_start(myear), "%d", &tm.tm_year);
486  if (tm.tm_year < 50)
487  tm.tm_year += 100;
488  else if (tm.tm_year >= 1900)
489  tm.tm_year -= 1900;
490 
491  /* Time */
492  int hour, min, sec = 0;
493  sscanf(s + mutt_regmatch_start(mhour), "%d", &hour);
494  sscanf(s + mutt_regmatch_start(mminute), "%d", &min);
495  if (mutt_regmatch_start(msecond) != -1)
496  sscanf(s + mutt_regmatch_start(msecond), "%d", &sec);
497  if ((hour > 23) || (min > 59) || (sec > 60))
498  return -1;
499  tm.tm_hour = hour;
500  tm.tm_min = min;
501  tm.tm_sec = sec;
502 
503  /* Time zone */
504  int zhours = 0;
505  int zminutes = 0;
506  bool zoccident = false;
507  if (mutt_regmatch_start(mtz) != -1)
508  {
509  char direction;
510  sscanf(s + mutt_regmatch_start(mtz), "%c%02d%02d", &direction, &zhours, &zminutes);
511  zoccident = (direction == '-');
512  }
513  else if (mutt_regmatch_start(mtzobs) != -1)
514  {
515  const struct Tz *tz =
516  find_tz(s + mutt_regmatch_start(mtzobs), mutt_regmatch_len(mtzobs));
517  if (tz)
518  {
519  zhours = tz->zhours;
520  zminutes = tz->zminutes;
521  zoccident = tz->zoccident;
522  }
523  }
524 
525  if (tz_out)
526  {
527  tz_out->zhours = zhours;
528  tz_out->zminutes = zminutes;
529  tz_out->zoccident = zoccident;
530  }
531 
532  return add_tz_offset(mutt_date_make_time(&tm, false), zoccident, zhours, zminutes);
533 }
Tue, 3 Mar [2020] 14:32:55 +0200
Definition: prex.h:127
Tue, [3] Mar 2020 14:32:55 +0200
Definition: prex.h:125
Tue, 3 Mar 2020 14:32:55[UT]
Definition: prex.h:172
Tue, 3 Mar 2020 14:32:[55] +0200
Definition: prex.h:168
static size_t mutt_regmatch_len(const regmatch_t *match)
Return the length of a match.
Definition: regex3.h:80
Tue, [3] Mar 2020 14:32:55 +0200
Definition: prex.h:156
Tue, 3 Mar 2020 14:[32]:55 +0200
Definition: prex.h:129
Tue, 3 Mar [2020] 14:32:55 +0200
Definition: prex.h:160
unsigned char zhours
Hours away from UTC.
Definition: date.h:45
Tue, 3 Mar 2020 14:32:55 [+0200]
Definition: prex.h:133
Tue, 3 [Jan] 2020 14:32:55 +0200
Definition: prex.h:126
Log at debug level 2.
Definition: logging.h:41
Tue, 3 Mar 2020 14:[32]:55 +0200
Definition: prex.h:164
[Mon, (Comment) 16 Mar 2020 15:09:35 -0700]
Definition: prex.h:38
bool zoccident
True if west of UTC, False if East.
Definition: date.h:47
Tue, 3 Mar 2020 14:32:55 [+0200]
Definition: prex.h:171
Tue, 3 Mar 2020 [14]:32:55 +0200
Definition: prex.h:128
regmatch_t * mutt_prex_capture(enum Prex which, const char *str)
match a precompiled regex against a string
Definition: prex.c:306
static const struct Tz * find_tz(const char *s, size_t len)
Look up a timezone.
Definition: date.c:173
static time_t add_tz_offset(time_t t, bool w, time_t h, time_t m)
Compute and add a timezone offset to an UTC time.
Definition: date.c:158
static regoff_t mutt_regmatch_start(const regmatch_t *match)
Return the start of a match.
Definition: regex3.h:60
Tue, 3 [Jan] 2020 14:32:55 +0200
Definition: prex.h:158
[Mon, 16 Mar 2020 15:09:35 -0700]
Definition: prex.h:37
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
Tue, 3 Mar 2020 14:32:[55] +0200
Definition: prex.h:131
int mutt_date_check_month(const char *s)
Is the string a valid month name.
Definition: date.c:401
#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:228
Tue, 3 Mar 2020 [14]:32:55 +0200
Definition: prex.h:162
Tue, 3 Mar 2020 14:32:55[UT]
Definition: prex.h:134
+ 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 544 of file date.c.

545 {
546  if (!buf)
547  return -1;
548 
549  struct tm tm = mutt_date_localtime(timestamp);
550  time_t tz = mutt_date_local_tz(timestamp);
551 
552  tz /= 60;
553 
554  return snprintf(buf, buflen, "%02d-%s-%d %02d:%02d:%02d %+03d%02d",
555  tm.tm_mday, Months[tm.tm_mon], tm.tm_year + 1900, tm.tm_hour,
556  tm.tm_min, tm.tm_sec, (int) tz / 60, (int) abs((int) tz) % 60);
557 }
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:641
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:205
+ 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 570 of file date.c.

571 {
572  if (!buf)
573  return -1;
574 
575  struct tm tm = mutt_date_gmtime(timestamp);
576  return snprintf(buf, buflen, "%s, %d %s %d %02d:%02d:%02d UTC",
577  Weekdays[tm.tm_wday], tm.tm_mday, Months[tm.tm_mon],
578  tm.tm_year + 1900, tm.tm_hour, tm.tm_min, tm.tm_sec);
579 }
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:659
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 587 of file date.c.

588 {
589  const regmatch_t *match = mutt_prex_capture(PREX_IMAP_DATE, s);
590  if (!match)
591  return 0;
592 
593  const regmatch_t *mday = &match[PREX_IMAP_DATE_MATCH_DAY];
594  const regmatch_t *mmonth = &match[PREX_IMAP_DATE_MATCH_MONTH];
595  const regmatch_t *myear = &match[PREX_IMAP_DATE_MATCH_YEAR];
596  const regmatch_t *mtime = &match[PREX_IMAP_DATE_MATCH_TIME];
597  const regmatch_t *mtz = &match[PREX_IMAP_DATE_MATCH_TZ];
598 
599  struct tm tm;
600 
601  sscanf(s + mutt_regmatch_start(mday), " %d", &tm.tm_mday);
602  tm.tm_mon = mutt_date_check_month(s + mutt_regmatch_start(mmonth));
603  sscanf(s + mutt_regmatch_start(myear), "%d", &tm.tm_year);
604  tm.tm_year -= 1900;
605  sscanf(s + mutt_regmatch_start(mtime), "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
606 
607  char direction;
608  int zhours, zminutes;
609  sscanf(s + mutt_regmatch_start(mtz), "%c%02d%02d", &direction, &zhours, &zminutes);
610  bool zoccident = (direction == '-');
611 
612  return add_tz_offset(mutt_date_make_time(&tm, false), zoccident, zhours, zminutes);
613 }
[16-MAR-2020 15:09:35 -0700]
Definition: prex.h:39
15-MAR-2020 15:09:35 [-0700]
Definition: prex.h:190
15-MAR-2020 [15:09:35] -0700
Definition: prex.h:189
15-MAR-[2020] 15:09:35 -0700
Definition: prex.h:188
[ 4]-MAR-2020 15:09:35 -0700
Definition: prex.h:184
regmatch_t * mutt_prex_capture(enum Prex which, const char *str)
match a precompiled regex against a string
Definition: prex.c:306
static time_t add_tz_offset(time_t t, bool w, time_t h, time_t m)
Compute and add a timezone offset to an UTC time.
Definition: date.c:158
static regoff_t mutt_regmatch_start(const regmatch_t *match)
Return the start of a match.
Definition: regex3.h:60
15-[MAR]-2020 15:09:35 -0700
Definition: prex.h:187
int mutt_date_check_month(const char *s)
Is the string a valid month name.
Definition: date.c:401
time_t mutt_date_make_time(struct tm *t, bool local)
Convert struct tm to time_t
Definition: date.c:228
+ 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,
time_t  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 623 of file date.c.

624 {
625  if (timeout < 0)
626  return now;
627 
628  if ((TIME_T_MAX - now) < timeout)
629  return TIME_T_MAX;
630 
631  return now + timeout;
632 }
#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 641 of file date.c.

642 {
643  struct tm tm = { 0 };
644 
645  if (t == MUTT_DATE_NOW)
646  t = mutt_date_epoch();
647 
648  localtime_r(&t, &tm);
649  return tm;
650 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:414
#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 659 of file date.c.

660 {
661  struct tm tm = { 0 };
662 
663  if (t == MUTT_DATE_NOW)
664  t = mutt_date_epoch();
665 
666  gmtime_r(&t, &tm);
667  return tm;
668 }
time_t mutt_date_epoch(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:414
#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 678 of file date.c.

679 {
680  if (!buf || !format)
681  return 0;
682 
683  struct tm tm = mutt_date_localtime(t);
684  return strftime(buf, buflen, format, &tm);
685 }
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:641
+ 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 691 of file date.c.

692 {
693  const struct timespec sleep = {
694  .tv_sec = ms / 1000,
695  .tv_nsec = (ms % 1000) * 1000000UL,
696  };
697  nanosleep(&sleep, NULL);
698 }
time_t tv_sec
Definition: file.h:48
Time value with nanosecond precision.
Definition: file.h:46
+ 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.