diff options
| author | Richard M. Stallman | 1995-04-17 06:10:39 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1995-04-17 06:10:39 +0000 |
| commit | 1b8fa736b3881e2e3a06af8cf105fa91d30f1557 (patch) | |
| tree | 54b9fa701ac143e48c8ead6cb4d0f4ebc239c1b9 /src | |
| parent | 61392e7b046c500ab8ebba2c082dbc50e0fa798f (diff) | |
| download | emacs-1b8fa736b3881e2e3a06af8cf105fa91d30f1557.tar.gz emacs-1b8fa736b3881e2e3a06af8cf105fa91d30f1557.zip | |
(Fencode_time): Rewrite by Naggum.
Diffstat (limited to 'src')
| -rw-r--r-- | src/editfns.c | 121 |
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\ | |||
| 741 | to the current time zone and daylight savings time if not specified; if\n\ | 741 | to the current time zone and daylight savings time if not specified; if\n\ |
| 742 | specified, it can be either a list (as from `current-time-zone') or an\n\ | 742 | specified, it can be either a list (as from `current-time-zone') or an\n\ |
| 743 | integer (as from `decode-time'), and is applied without consideration for\n\ | 743 | integer (as from `decode-time'), and is applied without consideration for\n\ |
| 744 | daylight savings time. If YEAR is less than 100, values in the range 0 to\n\ | 744 | daylight savings time.\n\ |
| 745 | 37 are interpreted as in the 21st century, all other values are in the 20th\n\ | 745 | If YEAR is less than 100, values in the range 0 through 69 are treated\n\ |
| 746 | century.") | 746 | as 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 | ||
| 822 | DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0, | 839 | DEFUN ("current-time-string", Fcurrent_time_string, Scurrent_time_string, 0, 1, 0, |