mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-23 07:19:15 +00:00
Some time-handling patches from Paul Eggert:
* editfns.c (Fcurrent_time_zone): Take an optional argument specifying what (absolute) time should be used to determine the current time zone. Yield just offset and name of time zone, including DST correction. Yield time zone offset in seconds, not minutes. (lisp_time_argument, difftm): New functions. (Fcurrent_time_string): Use lisp_time_argument. * systime.h (EMACS_CURRENT_TIME_ZONE, EMACS_GET_TZ_OFFSET, EMACS_GET_TZ_NAMES): Remove. * config.h.in: Add HAVE_TM_ZONE.
This commit is contained in:
parent
facb137b9c
commit
e3120ab527
@ -86,6 +86,7 @@ and this notice must be preserved on all copies. */
|
|||||||
#undef HAVE_GETTIMEOFDAY
|
#undef HAVE_GETTIMEOFDAY
|
||||||
#undef HAVE_GETHOSTNAME
|
#undef HAVE_GETHOSTNAME
|
||||||
#undef HAVE_DUP2
|
#undef HAVE_DUP2
|
||||||
|
#undef HAVE_TM_ZONE
|
||||||
#undef TM_IN_SYS_TIME
|
#undef TM_IN_SYS_TIME
|
||||||
#undef STDC_HEADERS
|
#undef STDC_HEADERS
|
||||||
#undef TIME_WITH_SYS_TIME
|
#undef TIME_WITH_SYS_TIME
|
||||||
|
134
src/editfns.c
134
src/editfns.c
@ -541,6 +541,27 @@ resolution finer than a second.")
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
lisp_time_argument (specified_time, result)
|
||||||
|
Lisp_Object specified_time;
|
||||||
|
time_t *result;
|
||||||
|
{
|
||||||
|
if (NILP (specified_time))
|
||||||
|
return time (result) != -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Lisp_Object high, low;
|
||||||
|
high = Fcar (specified_time);
|
||||||
|
CHECK_NUMBER (high, 0);
|
||||||
|
low = Fcdr (specified_time);
|
||||||
|
if (XTYPE (low) == Lisp_Cons)
|
||||||
|
low = Fcar (low);
|
||||||
|
CHECK_NUMBER (low, 0);
|
||||||
|
*result = (XINT (high) << 16) + (XINT (low) & 0xffff);
|
||||||
|
return *result >> 16 == XINT (high);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
|
DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,
|
||||||
"Return the current time, as a human-readable string.\n\
|
"Return the current time, as a human-readable string.\n\
|
||||||
Programs can use this function to decode a time,\n\
|
Programs can use this function to decode a time,\n\
|
||||||
@ -556,24 +577,12 @@ and from `file-attributes'.")
|
|||||||
(specified_time)
|
(specified_time)
|
||||||
Lisp_Object specified_time;
|
Lisp_Object specified_time;
|
||||||
{
|
{
|
||||||
long value;
|
time_t value;
|
||||||
char buf[30];
|
char buf[30];
|
||||||
register char *tem;
|
register char *tem;
|
||||||
|
|
||||||
if (NILP (specified_time))
|
if (! lisp_time_argument (specified_time, &value))
|
||||||
value = time ((long *) 0);
|
value = -1;
|
||||||
else
|
|
||||||
{
|
|
||||||
Lisp_Object high, low;
|
|
||||||
high = Fcar (specified_time);
|
|
||||||
CHECK_NUMBER (high, 0);
|
|
||||||
low = Fcdr (specified_time);
|
|
||||||
if (XTYPE (low) == Lisp_Cons)
|
|
||||||
low = Fcar (low);
|
|
||||||
CHECK_NUMBER (low, 0);
|
|
||||||
value = ((XINT (high) << 16) + (XINT (low) & 0xffff));
|
|
||||||
}
|
|
||||||
|
|
||||||
tem = (char *) ctime (&value);
|
tem = (char *) ctime (&value);
|
||||||
|
|
||||||
strncpy (buf, tem, 24);
|
strncpy (buf, tem, 24);
|
||||||
@ -582,42 +591,79 @@ and from `file-attributes'.")
|
|||||||
return build_string (buf);
|
return build_string (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 0, 0,
|
#define TM_YEAR_ORIGIN 1900
|
||||||
"Return the offset, savings state, and names for the current time zone.\n\
|
|
||||||
This returns a list of the form (OFFSET SAVINGS-FLAG STANDARD SAVINGS).\n\
|
/* Yield A - B, measured in seconds. */
|
||||||
OFFSET is an integer specifying how many minutes east of Greenwich the\n\
|
static long
|
||||||
current time zone is located. A negative value means west of\n\
|
difftm(a, b)
|
||||||
Greenwich. Note that this describes the standard time; if daylight\n\
|
struct tm *a, *b;
|
||||||
savings time is in effect, it does not affect this value.\n\
|
{
|
||||||
SAVINGS-FLAG is non-nil iff daylight savings time or some other sort\n\
|
int ay = a->tm_year + (TM_YEAR_ORIGIN - 1);
|
||||||
of seasonal time adjustment is in effect.\n\
|
int by = b->tm_year + (TM_YEAR_ORIGIN - 1);
|
||||||
STANDARD is a string giving the name of the time zone when no seasonal\n\
|
return
|
||||||
time adjustment is in effect.\n\
|
(
|
||||||
SAVINGS is a string giving the name of the time zone when there is a\n\
|
(
|
||||||
seasonal time adjustment in effect.\n\
|
(
|
||||||
If the local area does not use a seasonal time adjustment,\n\
|
/* difference in day of year */
|
||||||
SAVINGS-FLAG is always nil, and STANDARD and SAVINGS are equal.\n\
|
a->tm_yday - b->tm_yday
|
||||||
|
/* + intervening leap days */
|
||||||
|
+ ((ay >> 2) - (by >> 2))
|
||||||
|
- (ay/100 - by/100)
|
||||||
|
+ ((ay/100 >> 2) - (by/100 >> 2))
|
||||||
|
/* + difference in years * 365 */
|
||||||
|
+ (long)(ay-by) * 365
|
||||||
|
)*24 + (a->tm_hour - b->tm_hour)
|
||||||
|
)*60 + (a->tm_min - b->tm_min)
|
||||||
|
)*60 + (a->tm_sec - b->tm_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFUN ("current-time-zone", Fcurrent_time_zone, Scurrent_time_zone, 0, 1, 0,
|
||||||
|
"Return the offset and name for the local time zone.\n\
|
||||||
|
This returns a list of the form (OFFSET NAME).\n\
|
||||||
|
OFFSET is an integer number of seconds ahead of UTC (east of Greenwich).\n\
|
||||||
|
A negative value means west of Greenwich.\n\
|
||||||
|
NAME is a string giving the name of the time zone.\n\
|
||||||
|
If an argument is given, it specifies when the time zone offset is determined\n\
|
||||||
|
instead of using the current time. The argument should have the form:\n\
|
||||||
|
(HIGH . LOW)\n\
|
||||||
|
or the form:\n\
|
||||||
|
(HIGH LOW . IGNORED).\n\
|
||||||
|
Thus, you can use times obtained from `current-time'\n\
|
||||||
|
and from `file-attributes'.\n\
|
||||||
\n\
|
\n\
|
||||||
Some operating systems cannot provide all this information to Emacs;\n\
|
Some operating systems cannot provide all this information to Emacs;\n\
|
||||||
in this case, current-time-zone will return a list containing nil for\n\
|
in this case, current-time-zone will return a list containing nil for\n\
|
||||||
the data it can't find.")
|
the data it can't find.")
|
||||||
()
|
(specified_time)
|
||||||
|
Lisp_Object specified_time;
|
||||||
{
|
{
|
||||||
#ifdef EMACS_CURRENT_TIME_ZONE
|
time_t value;
|
||||||
int offset, savings_flag;
|
struct tm *t;
|
||||||
char standard[11];
|
|
||||||
char savings[11];
|
|
||||||
|
|
||||||
EMACS_CURRENT_TIME_ZONE (&offset, &savings_flag, standard, savings);
|
if (lisp_time_argument (specified_time, &value)
|
||||||
|
&& (t = gmtime(&value)) != 0)
|
||||||
return Fcons (make_number (offset),
|
{
|
||||||
Fcons ((savings_flag ? Qt : Qnil),
|
struct tm gmt = *t; /* Make a copy, in case localtime modifies *t. */
|
||||||
Fcons (build_string (standard),
|
long offset;
|
||||||
Fcons (build_string (savings),
|
char *s, buf[6];
|
||||||
Qnil))));
|
t = localtime(&value);
|
||||||
#else
|
offset = difftm(t, &gmt);
|
||||||
return Fmake_list (4, Qnil);
|
s = 0;
|
||||||
|
#ifdef HAVE_TM_ZONE
|
||||||
|
if (t->tm_zone)
|
||||||
|
s = t->tm_zone;
|
||||||
#endif
|
#endif
|
||||||
|
if (!s)
|
||||||
|
{
|
||||||
|
/* No local time zone name is available; use "+-NNNN" instead. */
|
||||||
|
long am = (offset < 0 ? -offset : offset) / 60;
|
||||||
|
sprintf (buf, "%c%02d%02d", (offset < 0 ? '-' : '+'), am/60, am%60);
|
||||||
|
s = buf;
|
||||||
|
}
|
||||||
|
return Fcons (make_number (offset), Fcons (build_string (s), Qnil));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Fmake_list (2, Qnil);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
111
src/systime.h
111
src/systime.h
@ -146,114 +146,3 @@ extern long timezone;
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif /* ! defined (USE_UTIME) */
|
#endif /* ! defined (USE_UTIME) */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* EMACS_CURRENT_TIME_ZONE (int *OFFSET, int *SAVINGS_FLAG,
|
|
||||||
char *STANDARD_ABBR, char *SAVINGS_ABBR);
|
|
||||||
expands to a statement which stores information about the current
|
|
||||||
time zone in its arguments.
|
|
||||||
|
|
||||||
*OFFSET is set to the number of minutes EAST of Greenwich at which
|
|
||||||
the site's time zone is located. This should describe the offset
|
|
||||||
to standard time only; if some sort of daylight savings time is in
|
|
||||||
effect, that should not affect this value. Note that the tm_gmtoff
|
|
||||||
member of the struct tm returned by localtime is adjusted for
|
|
||||||
daylight savings, so you don't want to use localtime to set
|
|
||||||
*OFFSET; gettimeofday does the right thing.
|
|
||||||
|
|
||||||
*SAVINGS_FLAG is set to 1 if some sort of daylight savings time is
|
|
||||||
currently in effect, or 0 if no seasonal adjustment is currently
|
|
||||||
active.
|
|
||||||
|
|
||||||
*STANDARD_ABBR points to an array of at least 10 characters, which
|
|
||||||
should be set to the standard abbreviation for the time zone name
|
|
||||||
when daylight savings time is not active. For example, EDT would
|
|
||||||
be appropriate for the Eastern time zone of the USA.
|
|
||||||
|
|
||||||
*SAVINGS_ABBR points to an array of at least 10 characters, which
|
|
||||||
should be set to the standard abbreviation for the time zone name
|
|
||||||
when daylight savings time is active. For example, EST would be
|
|
||||||
appropriate for the Eastern time zone of the USA.
|
|
||||||
|
|
||||||
If the operating system cannot provide all this information, then
|
|
||||||
this macro will not be defined. */
|
|
||||||
|
|
||||||
|
|
||||||
/* The operating system configuration file can define
|
|
||||||
EMACS_CURRENT_TIME_ZONE. If not, we'll take a shot at it here. */
|
|
||||||
|
|
||||||
#ifndef EMACS_CURRENT_TIME_ZONE
|
|
||||||
|
|
||||||
/* System V derivatives have a timezone global variable. */
|
|
||||||
#if defined(USG) || defined(VMS)
|
|
||||||
#define EMACS_GET_TZ_OFFSET(offset) \
|
|
||||||
do { \
|
|
||||||
tzset (); \
|
|
||||||
*(offset) = timezone; \
|
|
||||||
} while (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* If we have timeval, then we have gettimeofday; that's half the battle. */
|
|
||||||
#if defined (HAVE_TIMEVAL) && !defined (EMACS_GET_TZ_OFFSET)
|
|
||||||
#define EMACS_GET_TZ_OFFSET(offset) \
|
|
||||||
do { \
|
|
||||||
struct timeval dummy; \
|
|
||||||
struct timezone zoneinfo; \
|
|
||||||
\
|
|
||||||
gettimeofday (&dummy, &zoneinfo); \
|
|
||||||
*(offset) = -zoneinfo.tz_minuteswest; \
|
|
||||||
} while (0)
|
|
||||||
#endif /* ! defined (HAVE_TIMEVAL) */
|
|
||||||
|
|
||||||
/* The following sane systems have a tzname array. The timezone function
|
|
||||||
is a stupid idea; timezone names can only be determined geographically,
|
|
||||||
not by Greenwich offset. */
|
|
||||||
#if defined (ultrix) || defined (hpux) || defined (_AIX) || defined (USG) || defined(VMS)
|
|
||||||
|
|
||||||
#define EMACS_GET_TZ_NAMES(standard, savings) \
|
|
||||||
do { \
|
|
||||||
extern char *tzname[2]; \
|
|
||||||
strcpy ((standard), tzname[0]); \
|
|
||||||
strcpy ((savings), tzname[1]); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#else /* ! defined (ultrix) || defined (hpux) || defined (_AIX) */
|
|
||||||
/* If we are running SunOS, Mt. Xinu BSD, or MACH 2.5, these systems have a
|
|
||||||
timezone function. */
|
|
||||||
#if (defined (hp9000) && ! defined (hpux) && defined (unix)) || defined (MACH) || defined (sun) || defined (NeXT)
|
|
||||||
|
|
||||||
#define EMACS_GET_TZ_NAMES(standard, savings) \
|
|
||||||
do { \
|
|
||||||
struct timeval dummy; \
|
|
||||||
struct timezone zoneinfo; \
|
|
||||||
extern char *timezone (); \
|
|
||||||
\
|
|
||||||
gettimeofday (&dummy, &zoneinfo); \
|
|
||||||
strcpy ((standard), timezone (zoneinfo.tz_minuteswest, 0)); \
|
|
||||||
strcpy ((savings), timezone (zoneinfo.tz_minuteswest, 1)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#endif /* ! (defined (hp9000) && ! defined (hpux) && defined (unix)) || defined (MACH) || defined (sun) */
|
|
||||||
#endif /* ! defined (ultrix) || defined (hpux) || defined (_AIX) */
|
|
||||||
|
|
||||||
/* If we can get all the information we need, let's define the macro! */
|
|
||||||
#if defined (EMACS_GET_TZ_OFFSET) && defined (EMACS_GET_TZ_NAMES)
|
|
||||||
|
|
||||||
#define EMACS_CURRENT_TIME_ZONE(offset, savings_flag, standard, savings)\
|
|
||||||
do { \
|
|
||||||
EMACS_TIME t; \
|
|
||||||
long secs; \
|
|
||||||
struct tm *tmp; \
|
|
||||||
\
|
|
||||||
EMACS_GET_TIME (t); \
|
|
||||||
secs = EMACS_SECS (t); \
|
|
||||||
tmp = localtime (&secs); \
|
|
||||||
*(savings_flag) = tmp->tm_isdst; \
|
|
||||||
\
|
|
||||||
EMACS_GET_TZ_OFFSET (offset); \
|
|
||||||
EMACS_GET_TZ_NAMES (standard, savings); \
|
|
||||||
} while (0)
|
|
||||||
#endif /* ! defined (EMACS_GET_TZ_OFFSET) && defined (EMACS_GET_TZ_NAMES) */
|
|
||||||
|
|
||||||
#endif /* EMACS_CURRENT_TIME_ZONE */
|
|
||||||
|
Loading…
Reference in New Issue
Block a user