2017

                      1                   2                   3
    1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
Jan S M T W T F S S M T W T F S S M T W T F S S M T W T F S S M T
Feb W T F S S M T W T F S S M T W T F S S M T W T F S S M T
Mar W T F S S M T W T F S S M T W T F S S M T W T F S S M T W T F
Apr S S M T W T F S S M T W T F S S M T W T F S S M T W T F S S
May M T W T F S S M T W T F S S M T W T F S S M T W T F S S M T W
Jun T F S S M T W T F S S M T W T F S S M T W T F S S M T W T F
Jul S S M T W T F S S M T W T F S S M T W T F S S M T W T F S S M
Aug T W T F S S M T W T F S S M T W T F S S M T W T F S S M T W T
Sep F S S M T W T F S S M T W T F S S M T W T F S S M T W T F S
Oct S M T W T F S S M T W T F S S M T W T F S S M T W T F S S M T
Nov W T F S S M T W T F S S M T W T F S S M T W T F S S M T W T
Dec F S S M T W T F S S M T W T F S S M T W T F S S M T W T F S S
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { Mon, Tue, Wed, Thu, Fri, Sat, Sun };
char day_sym[] = "MTWTFSS";
enum { Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec };

int opt_c;
int opt_h;

int
leap_year(int year)
{
   if (year % 400 == 0)
      return 1;
   else
   if (year % 100 == 0)
      return 0;
   else
   if (year % 4 == 0)
      return 1;
   else
      return 0;
}

int
days_year(int year)
{
   return leap_year(year) ? 366 : 365;
}

int
days_month(int m, int y)
{
   /*            Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */
   int days[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

   if (m == Feb)
      return leap_year(y) ? 29 : 28;
   else
      return days[m];
}

int
cal(int m, int y)
{
   int a, i;

   a = Sat;
   for (i = 2000; i < y; i++)
      a = (a + days_year(i)) % 7;
   for (i = 0; i < m; i++)
      a = (a + days_month(i, y)) % 7;

   return a;
}

void
print_month(int d, int n)
{
   int i;

   for (i = 0; i < n; i++) {
      printf(" %c", day_sym[d++]);
      if (d == 7)
         d = 0; }
   putchar('\n');
}

void
head(void)
{
   int i, j;

   fputs("   ", stdout);
   for (i = 0; i < 3; i++) {
      for (j = 0; j < 9; j++)
         fputs("  ", stdout);
      printf(" %d", i + 1); }
   putchar('\n');

   fputs("   ", stdout);
   for (i = 0; i < 31; i++)
      printf(" %d", (i + 1) % 10);
   putchar('\n');
}

void
print_range(int from_m, int from_y, int to_m, int to_y)
{
   char *mon_name[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
   const int f = from_y * 12 + from_m;
   const int t = to_y   * 12 + to_m;
   int i, m, y;
   int day = cal(from_m, from_y);

   for (i = f; i <= t; i++) {
      y = i / 12;
      m = i % 12;
      fputs(mon_name[m], stdout);
      if (opt_h)
         printf(" %4d", y);
      print_month(day, days_month(m, y));
      day = (day + days_month(m, y)) % 7; }
}

void
check_routine(int m, int y)
{
   int c, d, i;

   for (i = 2000; i <= y; i++) {
      c = cal(0, i);
      d = days_year(i);
      printf("%c(%d) %d %d %d\n", day_sym[c], c, i, d, d % 7); }

   for (i = 0; i <= m; i++) {
      c = cal(i, y);
      d = days_month(i, y);
      printf("%c(%d) %d %d %d\n", day_sym[c], c, i, d, d % 7); }
}

int
parse_range(char * const s)
{
   int fy, fm, ty, tm;
   char *t = s;

   fy = strtol(t, &t, 10);
   if (*t++ != '-') return 0;

   fm = strtol(t, &t, 10);
   if (!*t) {
      ty = fy, tm = fm; goto L0; }
   if (*t++ != '/') goto err;

   ty = strtol(t, &t, 10);
   if (!*t) {
      tm = ty, ty = fy; goto L0; }
   if (*t++ != '-') goto err;

   tm = strtol(t, &t, 10);
   if (*t) goto err;

L0:
   if (fm == 0 || fm > 12 || tm == 0 || tm > 12) goto err;
   fm--; tm--;
   if (fy * 12 + fm > ty * 12 + tm) goto err;

   if (opt_c)
      check_routine(fm, fy);
   print_range(fm, fy, tm, ty);
   return 1;
err:
   fprintf(stderr, "invalid range: %s\n", s);
   return 1;
}

void
print_year(int y)
{
   if (opt_c)
      check_routine(0, y);
   if (!opt_h) {
      printf("\n%d\n", y);
      head(); }
   print_range(0, y, 11, y);
}

int
main(int argc, char **argv)
{
   int i, j, y, err = 0;

   for (i = 1; i < argc; i++) {
      if (*argv[i] == '-')
         for (j = 1; argv[i][j]; j++)
            switch (argv[i][j]) {
            case 'c':
               opt_c = 1;
               break;
            case 'h':
               opt_h = 1;
               break;
            default:
               fprintf(stderr, "invalid opt: %c\n", argv[i][j]);
               err = 1;
               break; }
      else if (parse_range(argv[i]))
         ;
      else if ((y = atoi(argv[i])) >= 2000) {
         print_year(y); }
      else {
         fprintf(stderr, "invalid arg: %s\n", argv[i]);
         err = 1; } }

   return err;
}
Back to index