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.)

View in manual

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));
}