root/kern/clock_subr.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. leapyear
  2. clock_ymdhms_to_secs
  3. clock_secs_to_ymdhms

    1 /*      $OpenBSD: clock_subr.c,v 1.2 2006/11/14 18:00:27 jmc Exp $      */
    2 /*      $NetBSD: clock_subr.c,v 1.3 1997/03/15 18:11:16 is Exp $        */
    3 
    4 /*
    5  * Copyright (c) 1988 University of Utah.
    6  * Copyright (c) 1982, 1990, 1993
    7  *      The Regents of the University of California.  All rights reserved.
    8  *
    9  * This code is derived from software contributed to Berkeley by
   10  * the Systems Programming Group of the University of Utah Computer
   11  * Science Department.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  * 3. Neither the name of the University nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  * from: Utah $Hdr: clock.c 1.18 91/01/21$
   38  *
   39  *      @(#)clock.c     8.2 (Berkeley) 1/12/94
   40  */
   41 
   42 /*
   43  * Generic routines to convert between a POSIX date
   44  * (seconds since 1/1/1970) and yr/mo/day/hr/min/sec
   45  * Derived from arch/hp300/hp300/clock.c
   46  */
   47 
   48 #include <sys/types.h>
   49 #include <sys/systm.h>
   50 
   51 #include <dev/clock_subr.h>
   52 
   53 static inline int leapyear(int year);
   54 #define FEBRUARY        2
   55 #define days_in_year(a)         (leapyear(a) ? 366 : 365)
   56 #define days_in_month(a)        (month_days[(a) - 1])
   57 
   58 static const int month_days[12] = {
   59         31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
   60 };
   61 
   62 /*
   63  * This inline avoids some unnecessary modulo operations
   64  * as compared with the usual macro:
   65  *   ( ((year % 4) == 0 &&
   66  *      (year % 100) != 0) ||
   67  *     ((year % 400) == 0) )
   68  * It is otherwise equivalent.
   69  */
   70 static inline int
   71 leapyear(int year)
   72 {
   73         int rv = 0;
   74 
   75         if ((year & 3) == 0) {
   76                 rv = 1;
   77                 if ((year % 100) == 0) {
   78                         rv = 0;
   79                         if ((year % 400) == 0)
   80                                 rv = 1;
   81                 }
   82         }
   83         return (rv);
   84 }
   85 
   86 time_t
   87 clock_ymdhms_to_secs(struct clock_ymdhms *dt)
   88 {
   89         time_t secs;
   90         int i, year, days;
   91 
   92         year = dt->dt_year;
   93 
   94         /*
   95          * Compute days since start of time.
   96          * First from years, then from months.
   97          */
   98         days = 0;
   99         for (i = POSIX_BASE_YEAR; i < year; i++)
  100                 days += days_in_year(i);
  101         if (leapyear(year) && dt->dt_mon > FEBRUARY)
  102                 days++;
  103 
  104         /* Months */
  105         for (i = 1; i < dt->dt_mon; i++)
  106                 days += days_in_month(i);
  107         days += (dt->dt_day - 1);
  108 
  109         /* Add hours, minutes, seconds. */
  110         secs = ((days
  111             * 24 + dt->dt_hour)
  112             * 60 + dt->dt_min)
  113             * 60 + dt->dt_sec;
  114 
  115         return (secs);
  116 }
  117 
  118 /* This function uses a copy of month_days[] */
  119 #undef  days_in_month
  120 #define days_in_month(a)        (mthdays[(a) - 1])
  121 
  122 void
  123 clock_secs_to_ymdhms(time_t secs, struct clock_ymdhms *dt)
  124 {
  125         int mthdays[12];
  126         int i, days;
  127         int rsec;       /* remainder seconds */
  128 
  129         bcopy(month_days, mthdays, sizeof(mthdays));
  130 
  131         days = secs / SECDAY;
  132         rsec = secs % SECDAY;
  133 
  134         /* Day of week (Note: 1/1/1970 was a Thursday) */
  135         dt->dt_wday = (days + 4) % 7;
  136 
  137         /* Subtract out whole years, counting them in i. */
  138         for (i = POSIX_BASE_YEAR; days >= days_in_year(i); i++)
  139                 days -= days_in_year(i);
  140         dt->dt_year = i;
  141 
  142         /* Subtract out whole months, counting them in i. */
  143         if (leapyear(i))
  144                 days_in_month(FEBRUARY) = 29;
  145         for (i = 1; days >= days_in_month(i); i++)
  146                 days -= days_in_month(i);
  147         dt->dt_mon = i;
  148 
  149         /* Days are what is left over (+1) from all that. */
  150         dt->dt_day = days + 1;
  151 
  152         /* Hours, minutes, seconds are easy */
  153         dt->dt_hour = rsec / 3600;
  154         rsec = rsec % 3600;
  155         dt->dt_min  = rsec / 60;
  156         rsec = rsec % 60;
  157         dt->dt_sec  = rsec;
  158 }

/* [<][>][^][v][top][bottom][index][help] */