Blame view

lib/date.c 3.12 KB
83d290c56   Tom Rini   SPDX: Convert all...
1
  // SPDX-License-Identifier: GPL-2.0+
0587dd173   wdenk   Initial revision
2
3
4
  /*
   * (C) Copyright 2001
   * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
0587dd173   wdenk   Initial revision
5
   */
0587dd173   wdenk   Initial revision
6
7
  #include <common.h>
  #include <command.h>
199e87c34   Simon Glass   dm: rtc: Rename g...
8
  #include <errno.h>
0587dd173   wdenk   Initial revision
9
  #include <rtc.h>
187231172   AKASHI Takahiro   lib: add mktime64...
10
  #include <linux/time.h>
0587dd173   wdenk   Initial revision
11

05429b6cf   AKASHI Takahiro   rtc: move date.c ...
12
  #if defined(CONFIG_LIB_DATE) || defined(CONFIG_TIMESTAMP)
0587dd173   wdenk   Initial revision
13
14
15
16
17
18
  
  #define FEBRUARY		2
  #define	STARTOFTIME		1970
  #define SECDAY			86400L
  #define SECYR			(SECDAY * 365)
  #define	leapyear(year)		((year) % 4 == 0)
53677ef18   Wolfgang Denk   Big white-space c...
19
20
  #define	days_in_year(a)		(leapyear(a) ? 366 : 365)
  #define	days_in_month(a)	(month_days[(a) - 1])
0587dd173   wdenk   Initial revision
21

36b898b6b   Simon Glass   rtc: Tidy up the ...
22
23
24
  static int month_offset[] = {
  	0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
  };
0587dd173   wdenk   Initial revision
25
26
27
  /*
   * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
   */
199e87c34   Simon Glass   dm: rtc: Rename g...
28
  int rtc_calc_weekday(struct rtc_time *tm)
0587dd173   wdenk   Initial revision
29
  {
36b898b6b   Simon Glass   rtc: Tidy up the ...
30
31
  	int leaps_to_date;
  	int last_year;
0587dd173   wdenk   Initial revision
32
  	int day;
0587dd173   wdenk   Initial revision
33

199e87c34   Simon Glass   dm: rtc: Rename g...
34
  	if (tm->tm_year < 1753)
36b898b6b   Simon Glass   rtc: Tidy up the ...
35
36
  		return -1;
  	last_year = tm->tm_year - 1;
0587dd173   wdenk   Initial revision
37

36b898b6b   Simon Glass   rtc: Tidy up the ...
38
39
  	/* Number of leap corrections to apply up to end of last year */
  	leaps_to_date = last_year / 4 - last_year / 100 + last_year / 400;
0587dd173   wdenk   Initial revision
40
41
42
43
44
  
  	/*
  	 * This year is a leap year if it is divisible by 4 except when it is
  	 * divisible by 100 unless it is divisible by 400
  	 *
36b898b6b   Simon Glass   rtc: Tidy up the ...
45
  	 * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 is.
0587dd173   wdenk   Initial revision
46
  	 */
36b898b6b   Simon Glass   rtc: Tidy up the ...
47
48
49
50
51
  	if (tm->tm_year % 4 == 0 &&
  	    ((tm->tm_year % 100 != 0) || (tm->tm_year % 400 == 0)) &&
  	    tm->tm_mon > 2) {
  		/* We are past Feb. 29 in a leap year */
  		day = 1;
0587dd173   wdenk   Initial revision
52
  	} else {
36b898b6b   Simon Glass   rtc: Tidy up the ...
53
  		day = 0;
0587dd173   wdenk   Initial revision
54
  	}
36b898b6b   Simon Glass   rtc: Tidy up the ...
55
56
57
  	day += last_year * 365 + leaps_to_date + month_offset[tm->tm_mon - 1] +
  			tm->tm_mday;
  	tm->tm_wday = day % 7;
199e87c34   Simon Glass   dm: rtc: Rename g...
58
59
  
  	return 0;
0587dd173   wdenk   Initial revision
60
  }
36b898b6b   Simon Glass   rtc: Tidy up the ...
61
62
  /*
   * Converts Gregorian date to seconds since 1970-01-01 00:00:00.
0587dd173   wdenk   Initial revision
63
64
65
66
67
68
   * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
   * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
   *
   * [For the Julian calendar (which was used in Russia before 1917,
   * Britain & colonies before 1752, anywhere else before 1582,
   * and is still in use by some communities) leave out the
36b898b6b   Simon Glass   rtc: Tidy up the ...
69
   * -year / 100 + year / 400 terms, and add 10.]
0587dd173   wdenk   Initial revision
70
71
72
73
   *
   * This algorithm was first published by Gauss (I think).
   *
   * WARNING: this function will overflow on 2106-02-07 06:28:16 on
36b898b6b   Simon Glass   rtc: Tidy up the ...
74
   * machines where long is 32-bit! (However, as time_t is signed, we
0587dd173   wdenk   Initial revision
75
76
   * will already get problems at other places on 2038-01-19 03:14:08)
   */
714209832   Simon Glass   dm: rtc: Rename m...
77
  unsigned long rtc_mktime(const struct rtc_time *tm)
0587dd173   wdenk   Initial revision
78
  {
714209832   Simon Glass   dm: rtc: Rename m...
79
80
81
82
83
  	int mon = tm->tm_mon;
  	int year = tm->tm_year;
  	int days, hours;
  
  	mon -= 2;
36b898b6b   Simon Glass   rtc: Tidy up the ...
84
85
  	if (0 >= (int)mon) {	/* 1..12 -> 11, 12, 1..10 */
  		mon += 12;	/* Puts Feb last since it has leap day */
0587dd173   wdenk   Initial revision
86
87
  		year -= 1;
  	}
714209832   Simon Glass   dm: rtc: Rename m...
88
89
90
91
92
  	days = (unsigned long)(year / 4 - year / 100 + year / 400 +
  			367 * mon / 12 + tm->tm_mday) +
  			year * 365 - 719499;
  	hours = days * 24 + tm->tm_hour;
  	return (hours * 60 + tm->tm_min) * 60 + tm->tm_sec;
0587dd173   wdenk   Initial revision
93
  }
05429b6cf   AKASHI Takahiro   rtc: move date.c ...
94
  #endif /* CONFIG_LIB_DATE || CONFIG_TIMESTAMP */
187231172   AKASHI Takahiro   lib: add mktime64...
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  
  #ifdef CONFIG_LIB_DATE
  /* for compatibility with linux code */
  time64_t mktime64(const unsigned int year, const unsigned int mon,
  		  const unsigned int day, const unsigned int hour,
  		  const unsigned int min, const unsigned int sec)
  {
  	struct rtc_time time;
  
  	time.tm_year = year;
  	time.tm_mon = mon;
  	time.tm_mday = day;
  	time.tm_hour = hour;
  	time.tm_min = min;
  	time.tm_sec = sec;
  
  	return (time64_t)rtc_mktime((const struct rtc_time *)&time);
  }
  #endif