MudOSa4DGD/
MudOSa4DGD/bin/
MudOSa4DGD/data/
MudOSa4DGD/doc/
MudOSa4DGD/doc/driver/
MudOSa4DGD/doc/efun/bitstrings/
MudOSa4DGD/doc/efun/command/
MudOSa4DGD/doc/efun/communication/
MudOSa4DGD/doc/efun/heart_beat/
MudOSa4DGD/doc/efun/interactive/
MudOSa4DGD/doc/efun/inventory/
MudOSa4DGD/doc/efun/living/
MudOSa4DGD/doc/efun/mappings/
MudOSa4DGD/doc/efun/strings/
MudOSa4DGD/doc/efun/uid/
MudOSa4DGD/doc/funs/
MudOSa4DGD/doc/language/
MudOSa4DGD/mudlib/dgd/doc/
MudOSa4DGD/mudlib/dgd/lib/include/dgd/
MudOSa4DGD/mudlib/dgd/lib/std/
MudOSa4DGD/mudlib/dgd/lib/sys/
MudOSa4DGD/mudlib/dgd/log/
MudOSa4DGD/mudlib/log/
MudOSa4DGD/mudlib/std/include/
MudOSa4DGD/mudlib/std/obj/
/*
 *  Copyright (C) 1994, 1995 Haijo Schipper (abigail@mars.ic.iaf.nl)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

# include "config.h"
# include "time.h"

private mixed weekday (int time, int arg) {
  return (arg == 2
              ? index (ctime (time) [0 .. 2], WEEK)
              : arg == 1 ? WEEKDAYS [ctime (time) [0 .. 2]]
                         : ctime (time) [0 .. 2]);
}

private mixed month (int time, int arg) {
  return (arg == 2
              ? index (ctime (time) [4 .. 6], YEAR)
              : arg == 1 ? MONTHS [ctime (time) [4 .. 6]]
                         : ctime (time) [4 .. 6]);
}

private int day (int time) {
  int d;
  sscanf (ctime (time), "%*s %*s %d %*s %*d", d);
  return (d);
}

private string ttime (int time) {
  string t;
  sscanf (ctime (time), "%*s %*s %*d %s %*d", t);
  return (t);
}

private string date (int time) {
  return (ctime (time) [0 .. 10] + ctime (time) [20 .. 23]);
}

private int year (int time) {
  int y;
  sscanf (ctime (time), "%*s %*s %*d %*s %d", y);
  return (y);
}

private int hour (int time) {
  int h;
  sscanf (ttime (time), "%d:%*d:%*d", h);
  return (h);
}

private int minute (int time) {
  int m;
  sscanf (ttime (time), "%*d:%d:%*d", m);
  return (m);
}

private int second (int time) {
  int s;
  sscanf (ttime (time), "%*d:%*d:%d", s);
  return (s);
}

# ifdef __TIME_ZONE__
/* European rules. DST from 2.00 last Sunday of March until 2.00 last    */
/*                 Sunday of September.                                  */
/* Note, this will change of 1996. DST will then run until October.      */
/* timezone () will take the new rules in account...                     */
/* The scedule will not hold in the UK and Ireland.                      */
/* I haven't tested all possibilities... Mail me if you find any bugs.   */
/* It looks complicated, but really, it isn't. It's just one expression! */
private string timezone (int time) {
  int mm, dd, ww;
  return (year (time) < FIRST_DST_CONVERSION_YEAR ||
             (mm = month (time, 2) + 1) < 3 ||
              mm > (year (time) < SECOND_DST_CONVERSION_YEAR ? 9 : 10)
             ? TZ                                   /* Jan Feb Oct Nov Dec */
             : mm != 3 && mm != (year (time) < SECOND_DST_CONVERSION_YEAR
                                             ? 9 : 10)
                  ? DSTZ                            /* Apr - Aug | Sep */
                  : mm == 3 
                       ? (dd = day (time)) < 25     /* Mar */
                            ? TZ                    /* First weeks */
                            : (ww = weekday (time, 2))
                                ? dd - ww <= 25     /* Not a Sunday */
                                    ? TZ            /* Before last Sunday */
                                    : DSTZ          /* After... */
                                : hour (time) <= 2
                                    ? TZ            /* Before 02.00 */
                                    : DSTZ          /* After... */
                  : mm == 9
                       ? dd < 24                    /* Sep */
                            ? DSTZ                  /* First weeks */
                            : (ww = weekday (time, 2))
                                ? dd - ww <= 24     /* Not a Sunday */
                                    ? DSTZ          /* Before last Sunday */
                                    : TZ            /* After ... */
                                : hour (time) <= 1  /* Last Sunday */
                                    ? DSTZ          /* Before 2.00 */
                                    : hour (time) == 2
                                        ? ctime (time ()) ==
                                          ctime (time () + 3600)
                                            ? DSTZ  /* First time between */
                                                    /* 2.00 and 3.00 */
                                            : TZ    /* Second time... */
                                        : TZ        /* After 3.00 */

                       : dd < 25                    /* Oct */
                            ? DSTZ                  /* First weeks */
                            : (ww = weekday (time, 2))
                                ? dd - ww <= 25     /* Not a Sunday */
                                    ? DSTZ          /* Before last Sunday */
                                    : TZ            /* After ... */
                                : hour (time) <= 1  /* Last Sunday */
                                    ? DSTZ          /* Before 2.00 */
                                    : hour (time) == 2
                                        ? ctime (time ()) ==
                                          ctime (time () + 3600)
                                            ? DSTZ  /* First time between */
                                                    /* 2.00 and 3.00 */
                                            : TZ    /* Second time... */
                                        : TZ);      /* After 3.00 */
}
# endif

private int leap_year (int year) {
  return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
}

private int day_of_year (int time) {
  int mm, dd, i, doy;
  for (i = 0, mm = month (time, 2); i < mm; doy += YEAR_IN_DAYS [i ++]);
  return (doy + (dd = day (time)) +
          (leap_year (year (time)) && (mm > 1 || mm == 1 && dd == 29) ? 1 : 0));
}


private int week_number (int time, int monday) {
  int doy, wn;
  wn = (doy = day_of_year (time) - 1) / 7;
  if (weekday (time, 2) <= doy % 7) {wn ++;}
  if (monday && (weekday (time, 2) == 0)) {wn --;}
  return (wn);
}