📄 time.c
字号:
/* $Id: time.c,v 1.4 2002/02/16 11:41:05 pefo Exp $ *//* * Copyright (c) 2001-2002 Opsycon AB (www.opsycon.se / www.opsycon.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Opsycon AB, Sweden. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#ifdef _KERNEL#undef _KERNEL#endif#include <stdio.h>#include <string.h>#include <ctype.h>#include <time.h>#include <stdlib.h>#include <pmon.h>int cmd_date __P((int, char *[]));time_t sys_time __P((time_t *));/* * Copyright (c) 1987 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Arthur Olson. * * Redistribution and use in source and binary forms are permitted * provided that the above copyright notice and this paragraph are * duplicated in all such forms and that any documentation, * advertising materials, and other materials related to such * distribution and use acknowledge that the software was developed * by the University of California, Berkeley. The name of the * University may not be used to endorse or promote products derived * from this software without specific prior written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */#define TZNAME_MAX 32#define TZ_MAX_CHARS 50 /* Maximum number of abbreviation characters */#define TZ_MAX_TYPES 10 /* Maximum number of local time types */#define TZ_MAX_TIMES 370#define SECS_PER_MIN 60#define MINS_PER_HOUR 60#define HOURS_PER_DAY 24#define DAYS_PER_WEEK 7#define DAYS_PER_NYEAR 365#define DAYS_PER_LYEAR 366#define SECS_PER_HOUR (SECS_PER_MIN * MINS_PER_HOUR)#define SECS_PER_DAY ((long) SECS_PER_HOUR * HOURS_PER_DAY)#define MONS_PER_YEAR 12#define TM_SUNDAY 0#define TM_MONDAY 1#define TM_TUESDAY 2#define TM_WEDNESDAY 3#define TM_THURSDAY 4#define TM_FRIDAY 5#define TM_SATURDAY 6#define TM_JANUARY 0#define TM_FEBRUARY 1#define TM_MARCH 2#define TM_APRIL 3#define TM_MAY 4#define TM_JUNE 5#define TM_JULY 6#define TM_AUGUST 7#define TM_SEPTEMBER 8#define TM_OCTOBER 9#define TM_NOVEMBER 10#define TM_DECEMBER 11#define TM_YEAR_BASE 1900#define EPOCH_YEAR 1970#define EPOCH_WDAY TM_THURSDAY#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))static const int mon_lengths[2][MONS_PER_YEAR] = { {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};static const int year_lengths[2] = { DAYS_PER_NYEAR, DAYS_PER_LYEAR};struct rule { int r_type; /* type of rule--see below */ int r_day; /* day number of rule */ int r_week; /* week number of rule */ int r_mon; /* month number of rule */ long r_time; /* transition time of rule */};#define RT_NONE 0#define RT_JULIAN_DAY 1 /* Jn - Julian day */#define RT_DAY_OF_YEAR 2 /* n - day of year */#define RT_MONTH_NTH_DAY_OF_WEEK 3 /* Mm.n.d - month, week, day of week */static struct tm *offtime __P((const time_t *clock, long offset));static void tzreset __P((void));time_tsys_time(time_t *p){ time_t t; t = tgt_gettime (); if(p != NULL) { *p = t; } return(t);}static struct tm *offtime(const time_t *clock, long offset){ struct tm * tmp; long days; long rem; int y; int yleap; const int * ip; static struct tm tm; tmp = &tm; days = *clock / SECS_PER_DAY; rem = *clock % SECS_PER_DAY; rem += offset; while (rem < 0) { rem += SECS_PER_DAY; --days; } while (rem >= SECS_PER_DAY) { rem -= SECS_PER_DAY; ++days; } tmp->tm_hour = (int) (rem / SECS_PER_HOUR); rem = rem % SECS_PER_HOUR; tmp->tm_min = (int) (rem / SECS_PER_MIN); tmp->tm_sec = (int) (rem % SECS_PER_MIN); tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYS_PER_WEEK); if (tmp->tm_wday < 0) tmp->tm_wday += DAYS_PER_WEEK; y = EPOCH_YEAR; if (days >= 0) for ( ; ; ) { yleap = isleap(y); if (days < (long) year_lengths[yleap]) break; ++y; days = days - (long) year_lengths[yleap]; } else do { --y; yleap = isleap(y); days = days + (long) year_lengths[yleap]; } while (days < 0); tmp->tm_year = y - TM_YEAR_BASE; tmp->tm_yday = (int) days; ip = mon_lengths[yleap]; for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon)) days = days - (long) ip[tmp->tm_mon]; tmp->tm_mday = (int) (days + 1); tmp->tm_isdst = 0; tmp->tm_zone = ""; tmp->tm_gmtoff = offset; return tmp;}struct tm *gmtime(const time_t *clock){ struct tm *res; res = offtime(clock, 0L); res->tm_zone = "GMT"; /* UCT ? */ return res;}/*** Given a pointer into a time zone string, scan until a character that is not** a valid character in a zone name is found. Return a pointer to that** character.*/static const char *getzname(register const char *strp){ char c; while ((c = *strp) != '\0' && !isdigit(c) && c != ',' && c != '-' && c != '+') ++strp; return strp;}/*** Given a pointer into a time zone string, extract a number from that string.** Check that the number is within a specified range; if it is not, return** NULL.** Otherwise, return a pointer to the first character not part of the number.*/static const char *getnum(const char * strp, int * const nump,const int min,const int max){ char c; int num; if (strp == NULL || !isdigit(*strp)) return NULL; num = 0; while ((c = *strp) != '\0' && isdigit(c)) { num = num * 10 + (c - '0'); if (num > max) return NULL; /* illegal value */ ++strp; } if (num < min) return NULL; /* illegal value */ *nump = num; return strp;}/*** Given a pointer into a time zone string, extract a number of seconds,** in hh[:mm[:ss]] form, from the string.** If any error occurs, return NULL.** Otherwise, return a pointer to the first character not part of the number** of seconds.*/static const char *getsecs(const char * strp,long * const secsp){ int num; strp = getnum(strp, &num, 0, HOURS_PER_DAY); if (strp == NULL) return NULL; *secsp = num * SECS_PER_HOUR; if (*strp == ':') { ++strp; strp = getnum(strp, &num, 0, MINS_PER_HOUR - 1); if (strp == NULL) return NULL; *secsp += num * SECS_PER_MIN; if (*strp == ':') { ++strp; strp = getnum(strp, &num, 0, SECS_PER_MIN - 1); if (strp == NULL) return NULL; *secsp += num; } } return strp;}/*** Given a pointer into a time zone string, extract an offset, in** [+-]hh[:mm[:ss]] form, from the string.** If any error occurs, return NULL.** Otherwise, return a pointer to the first character not part of the time.*/static const char *getoffset(const char *strp,long * const offsetp){ int neg; if (*strp == '-') { neg = 1; ++strp; } else if (isdigit(*strp) || *strp++ == '+') neg = 0; else return NULL; /* illegal offset */ strp = getsecs(strp, offsetp); if (strp == NULL) return NULL; /* illegal time */ if (neg) *offsetp = -*offsetp; return strp;}/*** Given a pointer into a time zone string, extract a rule in the form** date[/time]. See POSIX section 8 for the format of "date" and "time".** If a valid rule is not found, return NULL.** Otherwise, return a pointer to the first character not part of the rule.*/static const char *getrule(const char *strp,struct rule * const rulep){ if (*strp == 'J') { /* ** Julian day. */ rulep->r_type = RT_JULIAN_DAY; ++strp; strp = getnum(strp, &rulep->r_day, 1, DAYS_PER_NYEAR); } else if (*strp == 'M') { /* ** Month, week, day. */ rulep->r_type = RT_MONTH_NTH_DAY_OF_WEEK; ++strp; strp = getnum(strp, &rulep->r_mon, 1, MONS_PER_YEAR); if (strp == NULL) return NULL; if (*strp++ != '.') return NULL; strp = getnum(strp, &rulep->r_week, 1, 5); if (strp == NULL) return NULL; if (*strp++ != '.') return NULL; strp = getnum(strp, &rulep->r_day, 0, DAYS_PER_WEEK - 1); } else if (isdigit(*strp)) { /* ** Day of year. */ rulep->r_type = RT_DAY_OF_YEAR; strp = getnum(strp, &rulep->r_day, 0, DAYS_PER_LYEAR - 1); } else return NULL; /* invalid format */ if (strp == NULL) return NULL; if (*strp == '/') { /* ** Time specified. */ ++strp; strp = getsecs(strp, &rulep->r_time); } else rulep->r_time = 2 * SECS_PER_HOUR; /* default = 2:00:00 */ return strp;}/*** Given the Epoch-relative time of January 1, 00:00:00 GMT, in a year, the** year, a rule, and the offset from GMT at the time that rule takes effect,** calculate the Epoch-relative time that rule takes effect.*/static time_t transtime( const time_t janfirst, const int year, const struct rule * const rulep, const long offset){ int leapyear; time_t value; int i; int d, m1, yy0, yy1, yy2, dow; leapyear = isleap(year); switch (rulep->r_type) { default: return -1; case RT_JULIAN_DAY: /* ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap ** years. ** In non-leap years, or if the day number is 59 or less, just ** add SECSPERDAY times the day number-1 to the time of ** January 1, midnight, to get the day. */ value = janfirst + (rulep->r_day - 1) * SECS_PER_DAY; if (leapyear && rulep->r_day >= 60) value += SECS_PER_DAY; break; case RT_DAY_OF_YEAR: /* ** n - day of year. ** Just add SECSPERDAY times the day number to the time of ** January 1, midnight, to get the day. */ value = janfirst + rulep->r_day * SECS_PER_DAY; break; case RT_MONTH_NTH_DAY_OF_WEEK: /* ** Mm.n.d - nth "dth day" of month m. */ value = janfirst; for (i = 0; i < rulep->r_mon - 1; ++i) value += mon_lengths[leapyear][i] * SECS_PER_DAY; /* ** Use Zeller's Congruence to get day-of-week of first day of ** month. */ m1 = (rulep->r_mon + 9) % 12 + 1; yy0 = (rulep->r_mon <= 2) ? (year - 1) : year; yy1 = yy0 / 100; yy2 = yy0 % 100; dow = ((26 * m1 - 2) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7; if (dow < 0) dow += DAYS_PER_WEEK; /* ** "dow" is the day-of-week of the first day of the month. Get ** the day-of-month (zero-origin) of the first "dow" day of the ** month. */ d = rulep->r_day - dow; if (d < 0) d += DAYS_PER_WEEK; for (i = 1; i < rulep->r_week; ++i) { if (d + DAYS_PER_WEEK >= mon_lengths[leapyear][rulep->r_mon - 1]) break; d += DAYS_PER_WEEK; } /* ** "d" is the day-of-month (zero-origin) of the day we want. */ value += d * SECS_PER_DAY; break; } /* ** "value" is the Epoch-relative time of 00:00:00 GMT on the day in ** question. To get the Epoch-relative time of the specified local ** time on that day, add the transition time and the current offset ** from GMT. */ return value + rulep->r_time + offset;}static char tz_stdnam[TZNAME_MAX] = "UCT";static char tz_dstnam[TZNAME_MAX] = "UCT";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -