aboutsummaryrefslogtreecommitdiffstats
path: root/src/editfns.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/editfns.c')
-rw-r--r--src/editfns.c91
1 files changed, 40 insertions, 51 deletions
diff --git a/src/editfns.c b/src/editfns.c
index 5f89391ce22..83cd4bd5535 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -85,6 +85,8 @@ extern Lisp_Object w32_get_internal_run_time (void);
85#endif 85#endif
86 86
87static void time_overflow (void) NO_RETURN; 87static void time_overflow (void) NO_RETURN;
88static Lisp_Object format_time_string (char const *, ptrdiff_t, Lisp_Object,
89 int, time_t *, struct tm **);
88static int tm_diff (struct tm *, struct tm *); 90static int tm_diff (struct tm *, struct tm *);
89static void update_buffer_properties (EMACS_INT, EMACS_INT); 91static void update_buffer_properties (EMACS_INT, EMACS_INT);
90 92
@@ -1700,33 +1702,41 @@ For example, to produce full ISO 8601 format, use "%Y-%m-%dT%T%z".
1700usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */) 1702usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */)
1701 (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal) 1703 (Lisp_Object format_string, Lisp_Object timeval, Lisp_Object universal)
1702{ 1704{
1703 time_t value; 1705 time_t t;
1706 struct tm *tm;
1707
1708 CHECK_STRING (format_string);
1709 format_string = code_convert_string_norecord (format_string,
1710 Vlocale_coding_system, 1);
1711 return format_time_string (SSDATA (format_string), SBYTES (format_string),
1712 timeval, ! NILP (universal), &t, &tm);
1713}
1714
1715static Lisp_Object
1716format_time_string (char const *format, ptrdiff_t formatlen,
1717 Lisp_Object timeval, int ut, time_t *tval, struct tm **tmp)
1718{
1704 ptrdiff_t size; 1719 ptrdiff_t size;
1705 int usec; 1720 int usec;
1706 int ns; 1721 int ns;
1707 struct tm *tm; 1722 struct tm *tm;
1708 int ut = ! NILP (universal);
1709
1710 CHECK_STRING (format_string);
1711 1723
1712 if (! (lisp_time_argument (timeval, &value, &usec) 1724 if (! (lisp_time_argument (timeval, tval, &usec)
1713 && 0 <= usec && usec < 1000000)) 1725 && 0 <= usec && usec < 1000000))
1714 error ("Invalid time specification"); 1726 error ("Invalid time specification");
1715 ns = usec * 1000; 1727 ns = usec * 1000;
1716 1728
1717 format_string = code_convert_string_norecord (format_string,
1718 Vlocale_coding_system, 1);
1719
1720 /* This is probably enough. */ 1729 /* This is probably enough. */
1721 size = SBYTES (format_string); 1730 size = formatlen;
1722 if (size <= (STRING_BYTES_BOUND - 50) / 6) 1731 if (size <= (STRING_BYTES_BOUND - 50) / 6)
1723 size = size * 6 + 50; 1732 size = size * 6 + 50;
1724 1733
1725 BLOCK_INPUT; 1734 BLOCK_INPUT;
1726 tm = ut ? gmtime (&value) : localtime (&value); 1735 tm = ut ? gmtime (tval) : localtime (tval);
1727 UNBLOCK_INPUT; 1736 UNBLOCK_INPUT;
1728 if (! tm) 1737 if (! tm)
1729 time_overflow (); 1738 time_overflow ();
1739 *tmp = tm;
1730 1740
1731 synchronize_system_time_locale (); 1741 synchronize_system_time_locale ();
1732 1742
@@ -1737,9 +1747,7 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */)
1737 1747
1738 buf[0] = '\1'; 1748 buf[0] = '\1';
1739 BLOCK_INPUT; 1749 BLOCK_INPUT;
1740 result = emacs_nmemftime (buf, size, SSDATA (format_string), 1750 result = emacs_nmemftime (buf, size, format, formatlen, tm, ut, ns);
1741 SBYTES (format_string),
1742 tm, ut, ns);
1743 UNBLOCK_INPUT; 1751 UNBLOCK_INPUT;
1744 if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0')) 1752 if ((result > 0 && result < size) || (result == 0 && buf[0] == '\0'))
1745 return code_convert_string_norecord (make_unibyte_string (buf, result), 1753 return code_convert_string_norecord (make_unibyte_string (buf, result),
@@ -1747,9 +1755,7 @@ usage: (format-time-string FORMAT-STRING &optional TIME UNIVERSAL) */)
1747 1755
1748 /* If buffer was too small, make it bigger and try again. */ 1756 /* If buffer was too small, make it bigger and try again. */
1749 BLOCK_INPUT; 1757 BLOCK_INPUT;
1750 result = emacs_nmemftime (NULL, (size_t) -1, 1758 result = emacs_nmemftime (NULL, (size_t) -1, format, formatlen,
1751 SSDATA (format_string),
1752 SBYTES (format_string),
1753 tm, ut, ns); 1759 tm, ut, ns);
1754 UNBLOCK_INPUT; 1760 UNBLOCK_INPUT;
1755 if (STRING_BYTES_BOUND <= result) 1761 if (STRING_BYTES_BOUND <= result)
@@ -1994,51 +2000,34 @@ the data it can't find. */)
1994{ 2000{
1995 time_t value; 2001 time_t value;
1996 struct tm *t; 2002 struct tm *t;
1997 struct tm gmt; 2003 struct tm localtm;
1998 2004 struct tm *localt;
1999 if (!lisp_time_argument (specified_time, &value, NULL)) 2005 Lisp_Object zone_offset, zone_name;
2000 t = NULL; 2006
2001 else 2007 zone_offset = Qnil;
2002 { 2008 zone_name = format_time_string ("%Z", sizeof "%Z" - 1, specified_time,
2003 BLOCK_INPUT; 2009 0, &value, &localt);
2004 t = gmtime (&value); 2010 localtm = *localt;
2005 if (t) 2011 BLOCK_INPUT;
2006 { 2012 t = gmtime (&value);
2007 gmt = *t; 2013 UNBLOCK_INPUT;
2008 t = localtime (&value);
2009 }
2010 UNBLOCK_INPUT;
2011 }
2012 2014
2013 if (t) 2015 if (t)
2014 { 2016 {
2015 int offset = tm_diff (t, &gmt); 2017 int offset = tm_diff (&localtm, t);
2016 char *s = 0; 2018 zone_offset = make_number (offset);
2017 char buf[sizeof "+00" + INT_STRLEN_BOUND (int)]; 2019 if (SCHARS (zone_name) == 0)
2018
2019#ifdef HAVE_TM_ZONE
2020 if (t->tm_zone)
2021 s = (char *)t->tm_zone;
2022#else /* not HAVE_TM_ZONE */
2023#ifdef HAVE_TZNAME
2024 if (t->tm_isdst == 0 || t->tm_isdst == 1)
2025 s = tzname[t->tm_isdst];
2026#endif
2027#endif /* not HAVE_TM_ZONE */
2028
2029 if (!s)
2030 { 2020 {
2031 /* No local time zone name is available; use "+-NNNN" instead. */ 2021 /* No local time zone name is available; use "+-NNNN" instead. */
2032 int m = offset / 60; 2022 int m = offset / 60;
2033 int am = offset < 0 ? - m : m; 2023 int am = offset < 0 ? - m : m;
2024 char buf[sizeof "+00" + INT_STRLEN_BOUND (int)];
2034 sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60); 2025 sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60);
2035 s = buf; 2026 zone_name = build_string (buf);
2036 } 2027 }
2037
2038 return Fcons (make_number (offset), Fcons (build_string (s), Qnil));
2039 } 2028 }
2040 else 2029
2041 return Fmake_list (make_number (2), Qnil); 2030 return list2 (zone_offset, zone_name);
2042} 2031}
2043 2032
2044/* This holds the value of `environ' produced by the previous 2033/* This holds the value of `environ' produced by the previous