2006-03-27 13:16:34 +04:00
/*
* rtc and date / time utility functions
*
* Copyright ( C ) 2005 - 06 Tower Technologies
* Author : Alessandro Zummo < a . zummo @ towertech . it >
*
* based on arch / arm / common / rtctime . c and other bits
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/module.h>
# include <linux/rtc.h>
static const unsigned char rtc_days_in_month [ ] = {
31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31
} ;
2006-06-25 16:48:25 +04:00
static const unsigned short rtc_ydays [ 2 ] [ 13 ] = {
/* Normal years */
{ 0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334 , 365 } ,
/* Leap years */
{ 0 , 31 , 60 , 91 , 121 , 152 , 182 , 213 , 244 , 274 , 305 , 335 , 366 }
} ;
2006-03-27 13:16:34 +04:00
# define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
2006-06-25 16:48:25 +04:00
/*
* The number of days in the month .
*/
2006-03-27 13:16:34 +04:00
int rtc_month_days ( unsigned int month , unsigned int year )
{
2009-04-01 02:24:48 +04:00
return rtc_days_in_month [ month ] + ( is_leap_year ( year ) & & month = = 1 ) ;
2006-03-27 13:16:34 +04:00
}
EXPORT_SYMBOL ( rtc_month_days ) ;
2006-06-25 16:48:25 +04:00
/*
* The number of days since January 1. ( 0 to 365 )
*/
int rtc_year_days ( unsigned int day , unsigned int month , unsigned int year )
{
2009-04-01 02:24:48 +04:00
return rtc_ydays [ is_leap_year ( year ) ] [ month ] + day - 1 ;
2006-06-25 16:48:25 +04:00
}
EXPORT_SYMBOL ( rtc_year_days ) ;
2006-03-27 13:16:34 +04:00
/*
* Convert seconds since 01 - 01 - 1970 00 : 00 : 00 to Gregorian date .
*/
void rtc_time_to_tm ( unsigned long time , struct rtc_time * tm )
{
2008-09-03 01:36:05 +04:00
unsigned int month , year ;
int days ;
2006-03-27 13:16:34 +04:00
days = time / 86400 ;
2008-09-03 01:36:05 +04:00
time - = ( unsigned int ) days * 86400 ;
2006-03-27 13:16:34 +04:00
/* day of the week, 1970-01-01 was a Thursday */
tm - > tm_wday = ( days + 4 ) % 7 ;
year = 1970 + days / 365 ;
days - = ( year - 1970 ) * 365
+ LEAPS_THRU_END_OF ( year - 1 )
- LEAPS_THRU_END_OF ( 1970 - 1 ) ;
if ( days < 0 ) {
year - = 1 ;
2009-04-01 02:24:48 +04:00
days + = 365 + is_leap_year ( year ) ;
2006-03-27 13:16:34 +04:00
}
tm - > tm_year = year - 1900 ;
tm - > tm_yday = days + 1 ;
for ( month = 0 ; month < 11 ; month + + ) {
int newdays ;
newdays = days - rtc_month_days ( month , year ) ;
if ( newdays < 0 )
break ;
days = newdays ;
}
tm - > tm_mon = month ;
tm - > tm_mday = days + 1 ;
tm - > tm_hour = time / 3600 ;
time - = tm - > tm_hour * 3600 ;
tm - > tm_min = time / 60 ;
tm - > tm_sec = time - tm - > tm_min * 60 ;
}
EXPORT_SYMBOL ( rtc_time_to_tm ) ;
/*
* Does the rtc_time represent a valid date / time ?
*/
int rtc_valid_tm ( struct rtc_time * tm )
{
if ( tm - > tm_year < 70
2006-10-01 10:28:16 +04:00
| | ( ( unsigned ) tm - > tm_mon ) > = 12
2006-03-27 13:16:34 +04:00
| | tm - > tm_mday < 1
| | tm - > tm_mday > rtc_month_days ( tm - > tm_mon , tm - > tm_year + 1900 )
2006-10-01 10:28:16 +04:00
| | ( ( unsigned ) tm - > tm_hour ) > = 24
| | ( ( unsigned ) tm - > tm_min ) > = 60
| | ( ( unsigned ) tm - > tm_sec ) > = 60 )
2006-03-27 13:16:34 +04:00
return - EINVAL ;
return 0 ;
}
EXPORT_SYMBOL ( rtc_valid_tm ) ;
/*
* Convert Gregorian date to seconds since 01 - 01 - 1970 00 : 00 : 00.
*/
int rtc_tm_to_time ( struct rtc_time * tm , unsigned long * time )
{
* time = mktime ( tm - > tm_year + 1900 , tm - > tm_mon + 1 , tm - > tm_mday ,
tm - > tm_hour , tm - > tm_min , tm - > tm_sec ) ;
return 0 ;
}
EXPORT_SYMBOL ( rtc_tm_to_time ) ;
MODULE_LICENSE ( " GPL " ) ;