/* * day.c - 日数計算 * * Copyright (C) 1991, 2001, 2006 candy * */ static char rcsid[] = "$Id: day.c,v 2.1 1992/06/08 07:34:42 candy Exp candy $"; #include #include #include #include #include #include "calendar.h" char *myname; char usage_msg[] = "日数計算 V0.8091\n" "Usage: %s [-adnqv] [-F 区切り] 日付 {[+|-] 日付|.|p}\n" "Function: 日付の足し算と引き算ができます。\n" "\tday -d 1991.01.01 + 190 (1991.01.01 の 190 日後)\n" "\tday -n 1991.07.07 - 1991.03.03 (2つの日付の差)\n" "\tday -n 1991.07.07 (修正ユリウス日(MJD))\n" "\tday -a 1991.07.07 (ユリウス日(AJD))\n" "\t-q suppresses the output\n" "\toperator . prints current value and clear\n" "\toperator p prints current value\n" "日付は date の出力 \"Sun Dec 02 06:55:15 1979\" も可\n" ; static int datep; /* -d: yyyy-mm-dd で出力 */ static int nump; /* -n: 修正ユリウス日(MJD) で出力 */ static int ajdp; /* -a: AJD */ static int verbose; static int quiet; static char *ofs = "/"; static char * getword(const char *s_, char *d, size_t n, char **endp) { const unsigned char *s = s_; char *d0 = d; while (isspace(*s)) s++; if (*s == '\0') { d0 = NULL; } else { while (n >= 2 && *s != '\0' && !isspace(*s)) { *d++ = *s++; n--; }/* while */ } if (n >= 1) *d = '\0'; if (endp != NULL) { while (*s != '\0' && !isspace(*s)) s++; *endp = (char *)s; } return d0; }/* getword */ char delimiters[] = "-/,."; /* 区切り記号 */ /* * "yyyy-mm-dd" */ static int s_to_date(const char *str, char *delim, int *yy, int *mm, int *dd) { int err = -1, y = 0, m = 0, d = 0; str += strspn(str, delim); if (isdigit((unsigned char)*str)) { y = atoi(str); while (isdigit((unsigned char)*str)) str++; str += strspn(str, delim); if (isdigit((unsigned char)*str)) { m = atoi(str); while (isdigit((unsigned char)*str)) str++; str += strspn(str, delim); if (isdigit((unsigned char)*str)) { d = atoi(str); err = 0; } } } if (err == 0) { *yy = y; *mm = m; *dd = d; } return err; }/* s_to_date */ /* * Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec * 1 2 3 4 5 6 7 8 9 10 11 12 */ static int str_to_mon(const char *str) { static char *list[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL }; int x = 0; while (list[x] != NULL && strcmp(str, list[x]) != 0) x++; if (list[x] == NULL) x = -1; return x + 1; }/* str_to_mon */ /* * "Mon Jun 08 14:44:15 JST 1992\n" */ static int date_to_date(const char *date, int *yy, int *mm, int *dd) { int err = -1; char buf[16]; char *mv = (char *)date; if (getword(mv, buf, sizeof(buf), &mv) != NULL && getword(mv, buf, sizeof(buf), &mv) != NULL) { /* week was skipped */ *mm = str_to_mon(buf); if (getword(mv, buf, sizeof(buf), &mv) != NULL) { *dd = strtol(buf, NULL, 10); if (getword(mv, buf, sizeof(buf), &mv) != NULL && getword(mv, buf, sizeof(buf), &mv) != NULL) { /* hh:mm:ss was skipped */ if (isalpha((unsigned char)buf[0])) getword(mv, buf, sizeof(buf), &mv); /* skip timezone */ if (isdigit((unsigned char)buf[0])) { *yy = strtol(buf, NULL, 10); err = 0; } } } } return err; }/* date_to_date */ /* * */ static int str_to_date(const char *str, int *yy, int *mm, int *dd) { int err = date_to_date(str, yy, mm, dd); if (err != 0) { err = s_to_date(str, delimiters, yy, mm, dd); } return err; }/* str_to_date */ /* * 日付かどうか調べ */ static int is_date(const char *str) { int yy, mm, dd; return str_to_date(str, &yy, &mm, &dd) == 0; }/* is_date */ /* * */ static long calc_mjd(const char *str) { int year, month, day; long mjd = 0; if (is_date(str)) { str_to_date(str, &year, &month, &day); mjd = ymd_to_mjd(year, month, day); if (ajdp) mjd = mjd_to_ajd(mjd); } else { if (isdigit((unsigned char)*str)) { mjd = atoi(str); } else { fprintf(stderr, "%s: %s: invalid format\n", myname, str); } } return mjd; }/* calc_mjd */ /* * */ static int print_mjd(long mjd) { int year, month, day; long x = ajdp ? ajd_to_mjd(mjd) : mjd; mjd_to_ymd(x, &year, &month, &day); if (datep && nump) printf("%02d%s%02d%s%02d %ld\n", year, ofs, month, ofs, day, mjd); else { if (datep) printf("%02d%s%02d%s%02d\n", year, ofs, month, ofs, day); if (nump) printf("%ld\n", mjd); } return 0; }/* print_mjd */ static long total; /* * */ static long day(const char *str) { enum opecode {ADD, SUB}; static enum opecode ope = ADD; if (verbose) printf("%s\n", str); if (strcmp(str, ".") == 0) { print_mjd(total); ope = ADD; total = 0; } else if (strcmp(str, "p") == 0) { print_mjd(total); } else if (strcmp(str, "-") == 0) { ope = SUB; } else if (strcmp(str, "+") == 0) { ope = ADD; } else { long mjd = calc_mjd(str); if (ope == SUB) total -= mjd; else total += mjd; } return total; }/* day */ /* * */ #define isope(str) (((str)[0] == '-' || (str)[0] == '+') && (str)[1] == '\0') /* * */ static int fnain(FILE *fp) { char lbuf[1024]; long mjd = 0; while (fgets(lbuf, sizeof(lbuf), stdin) != NULL) { int len = strlen(lbuf); if (len > 0 && lbuf[len - 1] == '\n') lbuf[--len] = '\0'; total = 0; mjd = day(lbuf); if (!quiet) print_mjd(mjd); }/* while */ return 0; }/* fnain */ /* * */ static int nain(char *argv[]) { long mjd = 0; while (*argv != NULL) { mjd = day(*argv++); }/* while */ if (!quiet) print_mjd(mjd); return 0; }/* nain */ /* * */ #define ISFILE(str) (*(str) != '-' || *((str) + 1) == '\0') int main(int argc, char *argv[]) { int ch, show_usage = 0, result; myname = argv[0]; while ((ch = getopt(argc, argv, "adF:nvV")) != EOF) { switch (ch) { default: case 'V': show_usage++; break; case 'a': nump++; ajdp++; break; case 'd': datep++; break; case 'F': ofs = optarg; break; case 'n': nump++; break; case 'q': quiet++; break; case 'v': verbose++; break; }/* switch */ }/* while */ result = 1; if (show_usage) { fprintf(stderr, usage_msg, myname); } else { result = 0; if (nump == 0 && datep == 0) datep++; if (argc - optind == 0) fnain(stdin); else nain(&argv[optind]); /* argv[argc] must be NULL */ } return result; }/* main */