Function: decode-time
decode-time is a function defined in timefns.c.
Signature
(decode-time &optional TIME ZONE FORM)
Documentation
Decode a timestamp into (SEC MINUTE HOUR DAY MONTH YEAR DOW DST UTCOFF).
The optional TIME is the time value to convert. See
format-time-string for the various forms of a time value.
The optional ZONE is omitted or nil for Emacs local time, t for
Universal Time, wall for system wall clock time, or a string as in
the TZ environment variable. It can also be a list (as from
current-time-zone) or an integer (the UTC offset in seconds) applied
without consideration for daylight saving time.
The optional FORM specifies the form of the SEC member. If integer,
SEC is an integer; if t, SEC is an integer or (TICKS . HZ) timestamp
with the same precision as TIME. An omitted or nil FORM is currently
treated like integer, but this may change in future Emacs versions.
To access (or alter) the elements in the time value, the
decoded-time-second, decoded-time-minute, decoded-time-hour,
decoded-time-day, decoded-time-month, decoded-time-year,
decoded-time-weekday, decoded-time-dst and decoded-time-zone
accessors can be used.
The list has the following nine members: SEC is an integer or
Lisp timestamp representing a nonnegative value less than 60
(or less than 61 if the operating system supports leap seconds).
MINUTE is an integer between 0 and 59. HOUR is an integer
between 0 and 23. DAY is an integer between 1 and 31. MONTH is an
integer between 1 and 12. YEAR is the year number, an integer; 0
represents 1 BC. DOW is the day of week, an integer between 0 and 6,
where 0 is Sunday. DST is t if daylight saving time is in effect,
nil if it is not in effect, and -1 if daylight saving information is
not available. UTCOFF is an integer indicating the UTC offset in
seconds, i.e., the number of seconds east of Greenwich. (Note that
Common Lisp has different meanings for DOW and UTCOFF, and its
SEC is always an integer between 0 and 59.)
Probably introduced at or before Emacs version 19.29.
Aliases
org-decode-time (obsolete since 9.6)
Source Code
// Defined in /usr/src/emacs/src/timefns.c
{
/* Convert SPECIFIED_TIME to TIME_SPEC and HZ;
if HZ != 1 also set TH.ticks. */
time_t time_spec;
Lisp_Object hz;
struct ticks_hz th UNINIT;
if (EQ (form, Qt))
{
th = decode_lisp_time (specified_time, CFORM_TICKS_HZ).th;
struct timespec ts = ticks_hz_to_timespec (th.ticks, th.hz);
if (! timespec_valid_p (ts))
time_overflow ();
time_spec = ts.tv_sec;
hz = th.hz;
}
else
{
time_spec = lisp_seconds_argument (specified_time);
hz = make_fixnum (1);
}
/* Compute broken-down local time LOCAL_TM from TIME_SPEC and ZONE. */
struct tm local_tm, gmt_tm;
timezone_t tz = tzlookup (zone, false);
struct tm *tm = emacs_localtime_rz (tz, &time_spec, &local_tm);
xtzfree (tz);
if (!tm)
time_error (errno);
/* Let YEAR = LOCAL_TM.tm_year + TM_YEAR_BASE. */
Lisp_Object year;
if (FASTER_TIMEFNS
&& MOST_NEGATIVE_FIXNUM - TM_YEAR_BASE <= local_tm.tm_year
&& local_tm.tm_year <= MOST_POSITIVE_FIXNUM - TM_YEAR_BASE)
{
/* Avoid overflow when INT_MAX - TM_YEAR_BASE < local_tm.tm_year. */
EMACS_INT tm_year_base = TM_YEAR_BASE;
year = make_fixnum (local_tm.tm_year + tm_year_base);
}
else
{
mpz_set_si (mpz[0], local_tm.tm_year);
mpz_add_ui (mpz[0], mpz[0], TM_YEAR_BASE);
year = make_integer_mpz ();
}
/* Compute SEC from LOCAL_TM.tm_sec and HZ. */
Lisp_Object sec;
if (BASE_EQ (hz, make_fixnum (1)))
sec = make_fixnum (local_tm.tm_sec);
else
{
/* Let TICKS = HZ * LOCAL_TM.tm_sec + mod (TH.ticks, HZ)
and SEC = (TICKS . HZ). */
Lisp_Object ticks;
intmax_t n;
if (FASTER_TIMEFNS && FIXNUMP (th.ticks) && FIXNUMP (hz)
&& !ckd_mul (&n, XFIXNUM (hz), local_tm.tm_sec)
&& !ckd_add (&n, n, (XFIXNUM (th.ticks) % XFIXNUM (hz)
+ (XFIXNUM (th.ticks) % XFIXNUM (hz) < 0
? XFIXNUM (hz) : 0))))
ticks = make_int (n);
else
{
mpz_fdiv_r (mpz[0],
*bignum_integer (&mpz[0], th.ticks),
*bignum_integer (&mpz[1], hz));
mpz_addmul_ui (mpz[0], *bignum_integer (&mpz[1], hz),
local_tm.tm_sec);
ticks = make_integer_mpz ();
}
sec = Fcons (ticks, hz);
}
return CALLN (Flist,
sec,
make_fixnum (local_tm.tm_min),
make_fixnum (local_tm.tm_hour),
make_fixnum (local_tm.tm_mday),
make_fixnum (local_tm.tm_mon + 1),
year,
make_fixnum (local_tm.tm_wday),
(local_tm.tm_isdst < 0 ? make_fixnum (-1)
: local_tm.tm_isdst == 0 ? Qnil : Qt),
(HAVE_TM_GMTOFF
? make_fixnum (tm_gmtoff (&local_tm))
: gmtime_r (&time_spec, &gmt_tm)
? make_fixnum (tm_diff (&local_tm, &gmt_tm))
: Qnil));
}