aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRichard M. Stallman1995-04-17 06:10:39 +0000
committerRichard M. Stallman1995-04-17 06:10:39 +0000
commit1b8fa736b3881e2e3a06af8cf105fa91d30f1557 (patch)
tree54b9fa701ac143e48c8ead6cb4d0f4ebc239c1b9 /src
parent61392e7b046c500ab8ebba2c082dbc50e0fa798f (diff)
downloademacs-1b8fa736b3881e2e3a06af8cf105fa91d30f1557.tar.gz
emacs-1b8fa736b3881e2e3a06af8cf105fa91d30f1557.zip
(Fencode_time): Rewrite by Naggum.
Diffstat (limited to 'src')
-rw-r--r--src/editfns.c121
1 files changed, 69 insertions, 52 deletions
diff --git a/src/editfns.c b/src/editfns.c
index 3685b26e366..de98ee789ce 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -741,15 +741,15 @@ This is the reverse operation of `decode-time', which see. ZONE defaults\n\
741to the current time zone and daylight savings time if not specified; if\n\ 741to the current time zone and daylight savings time if not specified; if\n\
742specified, it can be either a list (as from `current-time-zone') or an\n\ 742specified, it can be either a list (as from `current-time-zone') or an\n\
743integer (as from `decode-time'), and is applied without consideration for\n\ 743integer (as from `decode-time'), and is applied without consideration for\n\
744daylight savings time. If YEAR is less than 100, values in the range 0 to\n\ 744daylight savings time.\n\
74537 are interpreted as in the 21st century, all other values are in the 20th\n\ 745If YEAR is less than 100, values in the range 0 through 69 are treated\n\
746century.") 746as 2000 through 2069; values 70 through 99 are treated as 1970...1999.")
747 (sec, min, hour, day, month, year, zone) 747 (sec, min, hour, day, month, year, zone)
748 Lisp_Object sec, min, hour, day, month, year, zone; 748 Lisp_Object sec, min, hour, day, month, year, zone;
749{ 749{
750 double universal; 750 time_t time;
751 int fullyear, mon; 751 int fullyear, mon, days, seconds, tz = 0;
752 static char days[11] = { 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31 }; 752 static char days_per_month[11] = { 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31 };
753 753
754 CHECK_NATNUM (sec, 0); 754 CHECK_NATNUM (sec, 0);
755 CHECK_NATNUM (min, 1); 755 CHECK_NATNUM (min, 1);
@@ -761,62 +761,79 @@ century.")
761 fullyear = XINT (year); 761 fullyear = XINT (year);
762 if (fullyear < 100) 762 if (fullyear < 100)
763 { 763 {
764 if (fullyear < 38) /* end of time: 2038-01-19 03:14:08 */ 764 if (fullyear < 70) /* Epoch is 1970. */
765 fullyear += 2000; 765 fullyear += 2000;
766 else 766 else
767 fullyear += 1900; 767 fullyear += 1900;
768 } 768 }
769 769
770 if (NILP (zone)) 770 /* Adjust incoming datespec to epoch = March 1, year 0. */
771 zone = Fcurrent_time_zone (Qnil); 771 mon = XINT (month) - 1 + 10;
772 if (CONSP (zone)) 772 fullyear += mon/12 - 1;
773 zone = Fcar (zone);
774
775 CHECK_NUMBER (zone, 6);
776
777 /* all of these should evaluate to compile-time constants. */
778#define MIN 60.0 /* 60 */
779#define HOUR (60*MIN) /* 3600 */
780#define DAY (24*HOUR) /* 86400 */
781#define YEAR (365*DAY) /* 31536000 */
782#define YEAR4 (4*YEAR+DAY) /* 126230400 */
783#define YEAR100 (25*YEAR4-DAY) /* 3155673600 */
784#define YEAR400 (4*YEAR100+DAY) /* 12622780800 */
785#define YEAR1900 (4*YEAR400+3*YEAR100) /* 59958144000 */
786#define YEAR1970 (YEAR1900+17*YEAR4+2*YEAR) /* 62167132800 */
787#define LEAPBIAS (59*DAY) /* 5097600 */
788
789 mon = XINT (month) - 1;
790 fullyear--;
791 mon += 10;
792 fullyear += mon/12;
793 mon %= 12; 773 mon %= 12;
794 774
795 universal = XINT (sec) + XINT (min) * MIN + XINT (hour) * HOUR; 775 days = XINT (day) - 1; /* day of month */
796 while (mon-- > 0) 776 while (mon-- > 0) /* day of year */
797 universal += days[mon] * DAY; 777 days += days_per_month[mon];
798 universal += (XINT (day) - 1) * DAY; 778 days += 146097 * (fullyear/400); /* 400 years = 146097 days */
799 universal += YEAR400 * (fullyear/400);
800 fullyear %= 400; 779 fullyear %= 400;
801 universal += YEAR100 * (fullyear/100); 780 days += 36524 * (fullyear/100); /* 100 years = 36524 days */
802 fullyear %= 100; 781 fullyear %= 100;
803 universal += YEAR4 * (fullyear/4); 782 days += 1461 * (fullyear/4); /* 4 years = 1461 days */
804 fullyear %= 4; 783 fullyear %= 4;
805 universal += YEAR * fullyear; 784 days += 365 * fullyear; /* 1 year = 365 days */
806 universal -= YEAR1970 - LEAPBIAS; 785
807 786 /* Adjust computed datespec to epoch = January 1, 1970. */
808 return make_time ((int)(universal - XINT (zone))); 787 days += 59; /* March 1 is 59th day. */
809 788 days -= 719527; /* 1970 years = 719527 days */
810#undef MIN 789
811#undef HOUR 790 seconds = XINT (sec) + 60 * XINT (min) + 3600 * XINT (hour);
812#undef DAY 791
813#undef YEAR 792 if (sizeof (time_t) == 4
814#undef YEAR4 793 && ((days+(seconds/86400) > 24854) || (days+(seconds/86400) < -24854)))
815#undef YEAR100 794 error ("the specified time is outside the representable range");
816#undef YEAR400 795
817#undef YEAR1900 796 time = days * 86400 + seconds;
818#undef YEAR1970 797
819#undef LEAPBIAS 798 /* We have the correct value for UTC. Adjust for timezones. */
799 if (NILP (zone))
800 {
801 struct tm gmt, *t;
802 time_t adjusted_time;
803 int adjusted_tz;
804 /* If the system does not use timezones, gmtime returns 0, and we
805 already have the correct value, by definition. */
806 if ((t = gmtime (&time)) != 0)
807 {
808 gmt = *t;
809 t = localtime (&time);
810 tz = difftm (t, &gmt);
811 /* The timezone returned is that at the specified Universal Time,
812 not the local time, which is what we want. Adjust, repeat. */
813 adjusted_time = time - tz;
814 gmt = *gmtime (&adjusted_time); /* this is safe now */
815 t = localtime (&adjusted_time);
816 adjusted_tz = difftm (t, &gmt);
817 /* In case of discrepancy, adjust again for extra accuracy. */
818 if (adjusted_tz != tz)
819 {
820 adjusted_time = time - adjusted_tz;
821 gmt = *gmtime (&adjusted_time);
822 t = localtime (&adjusted_time);
823 adjusted_tz = difftm (t, &gmt);
824 }
825 tz = adjusted_tz;
826 }
827 }
828 else
829 {
830 if (CONSP (zone))
831 zone = Fcar (zone);
832 CHECK_NUMBER (zone, 6);
833 tz = XINT (zone);
834 }
835
836 return make_time (time - tz);
820} 837}
821 838
822DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0, 839DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0,