uboot/drivers/rtc/date.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2001
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8/*
   9 * Date & Time support for Philips PCF8563 RTC
  10 */
  11
  12#include <common.h>
  13#include <command.h>
  14#include <errno.h>
  15#include <rtc.h>
  16
  17#if defined(CONFIG_CMD_DATE) || defined(CONFIG_TIMESTAMP)
  18
  19#define FEBRUARY                2
  20#define STARTOFTIME             1970
  21#define SECDAY                  86400L
  22#define SECYR                   (SECDAY * 365)
  23#define leapyear(year)          ((year) % 4 == 0)
  24#define days_in_year(a)         (leapyear(a) ? 366 : 365)
  25#define days_in_month(a)        (month_days[(a) - 1])
  26
  27static int month_days[12] = {
  28        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  29};
  30
  31/*
  32 * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
  33 */
  34int rtc_calc_weekday(struct rtc_time *tm)
  35{
  36        int leapsToDate;
  37        int lastYear;
  38        int day;
  39        int MonthOffset[] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
  40
  41        if (tm->tm_year < 1753)
  42                return -EINVAL;
  43        lastYear=tm->tm_year-1;
  44
  45        /*
  46         * Number of leap corrections to apply up to end of last year
  47         */
  48        leapsToDate = lastYear/4 - lastYear/100 + lastYear/400;
  49
  50        /*
  51         * This year is a leap year if it is divisible by 4 except when it is
  52         * divisible by 100 unless it is divisible by 400
  53         *
  54         * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 will be
  55         */
  56        if((tm->tm_year%4==0) &&
  57           ((tm->tm_year%100!=0) || (tm->tm_year%400==0)) &&
  58           (tm->tm_mon>2)) {
  59                /*
  60                 * We are past Feb. 29 in a leap year
  61                 */
  62                day=1;
  63        } else {
  64                day=0;
  65        }
  66
  67        day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + tm->tm_mday;
  68
  69        tm->tm_wday=day%7;
  70
  71        return 0;
  72}
  73
  74int rtc_to_tm(int tim, struct rtc_time *tm)
  75{
  76        register int    i;
  77        register long   hms, day;
  78
  79        day = tim / SECDAY;
  80        hms = tim % SECDAY;
  81
  82        /* Hours, minutes, seconds are easy */
  83        tm->tm_hour = hms / 3600;
  84        tm->tm_min = (hms % 3600) / 60;
  85        tm->tm_sec = (hms % 3600) % 60;
  86
  87        /* Number of years in days */
  88        for (i = STARTOFTIME; day >= days_in_year(i); i++) {
  89                day -= days_in_year(i);
  90        }
  91        tm->tm_year = i;
  92
  93        /* Number of months in days left */
  94        if (leapyear(tm->tm_year)) {
  95                days_in_month(FEBRUARY) = 29;
  96        }
  97        for (i = 1; day >= days_in_month(i); i++) {
  98                day -= days_in_month(i);
  99        }
 100        days_in_month(FEBRUARY) = 28;
 101        tm->tm_mon = i;
 102
 103        /* Days are what is left over (+1) from all that. */
 104        tm->tm_mday = day + 1;
 105
 106        /* Zero unused fields */
 107        tm->tm_yday = 0;
 108        tm->tm_isdst = 0;
 109
 110        /*
 111         * Determine the day of week
 112         */
 113        return rtc_calc_weekday(tm);
 114}
 115
 116/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
 117 * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
 118 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
 119 *
 120 * [For the Julian calendar (which was used in Russia before 1917,
 121 * Britain & colonies before 1752, anywhere else before 1582,
 122 * and is still in use by some communities) leave out the
 123 * -year/100+year/400 terms, and add 10.]
 124 *
 125 * This algorithm was first published by Gauss (I think).
 126 *
 127 * WARNING: this function will overflow on 2106-02-07 06:28:16 on
 128 * machines were long is 32-bit! (However, as time_t is signed, we
 129 * will already get problems at other places on 2038-01-19 03:14:08)
 130 */
 131unsigned long rtc_mktime(const struct rtc_time *tm)
 132{
 133        int mon = tm->tm_mon;
 134        int year = tm->tm_year;
 135        int days, hours;
 136
 137        mon -= 2;
 138        if (0 >= (int)mon) {    /* 1..12 -> 11,12,1..10 */
 139                mon += 12;              /* Puts Feb last since it has leap day */
 140                year -= 1;
 141        }
 142
 143        days = (unsigned long)(year / 4 - year / 100 + year / 400 +
 144                        367 * mon / 12 + tm->tm_mday) +
 145                        year * 365 - 719499;
 146        hours = days * 24 + tm->tm_hour;
 147        return (hours * 60 + tm->tm_min) * 60 + tm->tm_sec;
 148}
 149
 150#endif
 151