int week(int day, int month, int year) { int yearday; int firstweekday; int weekday; int firstday; int firstsunday; int shift; if (mflag) return isoweek(day, month, year); yearday = day_in_year(day, month, year); firstweekday = day_in_week(1, 1, year) + 1; weekday = day_in_week(day, month, year) + 1; firstday = day_in_year(1, 1, year); firstsunday = firstday + (8 - firstweekday); shift = 1; if (yearday < firstsunday) return (1); if (firstweekday > THURSDAY - 1) shift = 2; return ((((yearday + 1) - (weekday - 1)) / 7) + shift); }
/* * day_array -- * Fill in an array of 42 integers with a calendar. Assume for a moment * that you took the (maximum) 6 rows in a calendar and stretched them * out end to end. You would have 42 numbers or spaces. This routine * builds that array for any month from Jan. 1 through Dec. 9999. */ void day_array(int day, int month, int year, int *days) { int julday, daynum, dw, dm; int *d_sep1752; if (month == 9 && year == 1752) { int sep1752_ofs = (weekstart + SEP1752_OFS) % 7; d_sep1752 = julian ? j_sep1752 : sep1752; memcpy(days, d_sep1752 + sep1752_ofs, MAXDAYS * sizeof(int)); for (dm=0; dm<MAXDAYS; dm++) if (j_sep1752[dm + sep1752_ofs] == day) days[dm] |= TODAY_FLAG; return; } memcpy(days, empty, MAXDAYS * sizeof(int)); dm = days_in_month[leap_year(year)][month]; dw = (day_in_week(1, month, year) - weekstart + 7) % 7; julday = day_in_year(1, month, year); daynum = julian ? julday : 1; while (dm--) { days[dw] = daynum++; if (julday++ == day) days[dw] |= TODAY_FLAG; dw++; } }
/* * day_in_week * return the 0 based day number for any date from 1 Jan. 1 to * 31 Dec. 9999. Assumes the Gregorian reformation eliminates * 3 Sep. 1752 through 13 Sep. 1752. Returns Thursday for all * missing days. */ int day_in_week(int day, int month, int year) { long temp; temp = (long)(year - 1) * 365 + leap_years_since_year_1(year - 1) + day_in_year(day, month, year); if (temp < FIRST_MISSING_DAY) return ((temp - 1 + SATURDAY) % 7); if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) return (((temp - 1 + SATURDAY) - NUMBER_MISSING_DAYS) % 7); return (THURSDAY); }
/* * day_array -- * Fill in an array of 42 integers with a calendar. Assume for a moment * that you took the (maximum) 6 rows in a calendar and stretched them * out end to end. You would have 42 numbers or spaces. This routine * builds that array for any month from Jan. 1 through Dec. 9999. */ void day_array(int month, int year, int *days) { int day, dw, dm; if (month == 9 && year == 1752) { memmove(days, sep1752, MAXDAYS * sizeof(int)); return; } memmove(days, empty, MAXDAYS * sizeof(int)); dm = days_in_month[leap_year(year)][month]; dw = day_in_week(mflag?0:1, month, year); day = julian ? day_in_year(1, month, year) : 1; while (dm--) days[dw++] = day++; }
// number of days since Jan 1, 1970 (day 0) long int days_linear(const Date& d) { if (d.year() < first_date.year()) error("days_linear: year must be 1970 or later"); int y = d.year() - first_date.year(); return y*365 + n_leapyears(d.year()) + day_in_year(d) - 1; }
int main(int argc, char **argv) { struct tm *local_time; time_t now; int ch, day, month, year, yflag; char *progname, *p; int num_months = NUM_MONTHS; progname = argv[0]; if ((p = strrchr(progname, '/')) != NULL) progname = p+1; __progname = progname; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); #if defined(HAVE_LIBNCURSES) || defined(HAVE_LIBNCURSESW) || defined(HAVE_LIBTERMCAP) if ((term = getenv("TERM"))) { int ret; my_setupterm(term, 1, &ret); if (ret > 0) { Senter = my_tgetstr("so","smso"); Sexit = my_tgetstr("se","rmso"); Slen = strlen(Senter) + strlen(Sexit); } } #endif /* * The traditional Unix cal utility starts the week at Sunday, * while ISO 8601 starts at Monday. We read the start day from * the locale database, which can be overridden with the * -s (Sunday) or -m (Monday) options. */ #if HAVE_DECL__NL_TIME_WEEK_1STDAY /* * You need to use 2 locale variables to get the first day of the week. * This is needed to support first_weekday=2 and first_workday=1 for * the rare case where working days span across 2 weeks. * This shell script shows the combinations and calculations involved: for LANG in en_US ru_RU fr_FR csb_PL POSIX; do printf "%s:\t%s + %s -1 = " $LANG $(locale week-1stday first_weekday) date -d"$(locale week-1stday) +$(($(locale first_weekday)-1))day" +%w done en_US: 19971130 + 1 -1 = 0 #0 = sunday ru_RU: 19971130 + 2 -1 = 1 fr_FR: 19971201 + 1 -1 = 1 csb_PL: 19971201 + 2 -1 = 2 POSIX: 19971201 + 7 -1 = 0 */ { int wfd; union { unsigned int word; char *string; } val; val.string = nl_langinfo(_NL_TIME_WEEK_1STDAY); wfd = val.word; wfd = day_in_week(wfd % 100, (wfd / 100) % 100, wfd / (100 * 100)); weekstart = (wfd + *nl_langinfo(_NL_TIME_FIRST_WEEKDAY) - 1) % 7; } #endif yflag = 0; while ((ch = getopt(argc, argv, "13mjsyV")) != -1) switch(ch) { case '1': num_months = 1; /* default */ break; case '3': num_months = 3; break; case 's': weekstart = 0; /* default */ break; case 'm': weekstart = 1; break; case 'j': julian = 1; break; case 'y': yflag = 1; break; case 'V': printf(_("%s from %s\n"), progname, PACKAGE_STRING); return 0; case '?': default: usage(); } argc -= optind; argv += optind; time(&now); local_time = localtime(&now); day = month = year = 0; switch(argc) { case 3: if ((day = atoi(*argv++)) < 1 || day > 31) errx(1, _("illegal day value: use 1-%d"), 31); /* FALLTHROUGH */ case 2: if ((month = atoi(*argv++)) < 1 || month > 12) errx(1, _("illegal month value: use 1-12")); /* FALLTHROUGH */ case 1: if ((year = atoi(*argv)) < 1 || year > 9999) errx(1, _("illegal year value: use 1-9999")); if (day) { int dm = days_in_month[leap_year(year)][month]; if (day > dm) errx(1, _("illegal day value: use 1-%d"), dm); day = day_in_year(day, month, year); } else if ((local_time->tm_year + 1900) == year) { day = local_time->tm_yday + 1; } if (!month) yflag=1; break; case 0: day = local_time->tm_yday + 1; year = local_time->tm_year + 1900; month = local_time->tm_mon + 1; break; default: usage(); } headers_init(); if (!isatty(1)) day = 0; /* don't highlight */ if (yflag && julian) j_yearly(day, year); else if (yflag) yearly(day, year); else if (num_months == 1) monthly(day, month, year); else if (num_months == 3) monthly3(day, month, year); exit(0); }