Applied patch by Julun: time computations based on an algorithm by Fliegel,
and van Flandern (1968), instead of those inefficient loops we had before. Thanks! git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22557 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d5fb5794c6
commit
6a0f39da22
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
* Copyright 2006-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||||
* Copyright 2003, Jeff Ward, jeff@r2d2.stcloudstate.edu. All rights reserved.
|
* Copyright 2003, Jeff Ward, jeff@r2d2.stcloudstate.edu. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
@ -13,7 +13,7 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
#define RTC_EPOCHE_BASE_YEAR 1970
|
#define RTC_EPOCH_BASE_YEAR 1970
|
||||||
|
|
||||||
typedef struct rtc_info {
|
typedef struct rtc_info {
|
||||||
uint32 time;
|
uint32 time;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de
|
* Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de
|
||||||
* Copyright 2003, Jeff Ward, jeff@r2d2.stcloudstate.edu. All rights reserved.
|
* Copyright 2003, Jeff Ward, jeff@r2d2.stcloudstate.edu. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
@ -141,7 +141,7 @@ cmos_to_secs(const cmos_time *cmos)
|
|||||||
{
|
{
|
||||||
struct tm t;
|
struct tm t;
|
||||||
t.tm_year = bcd_to_int(cmos->century) * 100 + bcd_to_int(cmos->year)
|
t.tm_year = bcd_to_int(cmos->century) * 100 + bcd_to_int(cmos->year)
|
||||||
- RTC_EPOCHE_BASE_YEAR;
|
- RTC_EPOCH_BASE_YEAR;
|
||||||
t.tm_mon = bcd_to_int(cmos->month) - 1;
|
t.tm_mon = bcd_to_int(cmos->month) - 1;
|
||||||
t.tm_mday = bcd_to_int(cmos->day);
|
t.tm_mday = bcd_to_int(cmos->day);
|
||||||
t.tm_hour = bcd_to_int(cmos->hour);
|
t.tm_hour = bcd_to_int(cmos->hour);
|
||||||
@ -160,7 +160,7 @@ secs_to_cmos(uint32 seconds, cmos_time *cmos)
|
|||||||
struct tm t;
|
struct tm t;
|
||||||
rtc_secs_to_tm(seconds, &t);
|
rtc_secs_to_tm(seconds, &t);
|
||||||
|
|
||||||
wholeYear = t.tm_year + RTC_EPOCHE_BASE_YEAR;
|
wholeYear = t.tm_year + RTC_EPOCH_BASE_YEAR;
|
||||||
|
|
||||||
cmos->century = int_to_bcd(wholeYear / 100);
|
cmos->century = int_to_bcd(wholeYear / 100);
|
||||||
cmos->year = int_to_bcd(wholeYear % 100);
|
cmos->year = int_to_bcd(wholeYear % 100);
|
||||||
|
@ -23,6 +23,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define RTC_SECONDS_DAY 86400
|
||||||
|
#define RTC_EPOCH_JULIAN_DAY 2440588
|
||||||
|
// January 1st, 1970
|
||||||
|
|
||||||
static struct real_time_data *sRealTimeData;
|
static struct real_time_data *sRealTimeData;
|
||||||
static bool sIsGMT = false;
|
static bool sIsGMT = false;
|
||||||
static char sTimezoneFilename[B_PATH_NAME_LENGTH] = "";
|
static char sTimezoneFilename[B_PATH_NAME_LENGTH] = "";
|
||||||
@ -161,130 +165,58 @@ get_rtc_info(rtc_info *info)
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
#define SECONDS_31 2678400
|
/*! Converts the \a tm data to seconds. Note that the base year is not
|
||||||
#define SECONDS_30 2592000
|
1900 as in POSIX, but 1970.
|
||||||
#define SECONDS_28 2419200
|
*/
|
||||||
#define SECONDS_DAY 86400
|
|
||||||
|
|
||||||
static uint32 sSecsPerMonth[12] = {SECONDS_31, SECONDS_28, SECONDS_31, SECONDS_30,
|
|
||||||
SECONDS_31, SECONDS_30, SECONDS_31, SECONDS_31, SECONDS_30, SECONDS_31, SECONDS_30,
|
|
||||||
SECONDS_31};
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
leap_year(uint32 year)
|
|
||||||
{
|
|
||||||
if (year % 400 == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (year % 100 == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (year % 4 == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline uint32
|
|
||||||
secs_this_year(uint32 year)
|
|
||||||
{
|
|
||||||
if (leap_year(year))
|
|
||||||
return 31622400;
|
|
||||||
|
|
||||||
return 31536000;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
rtc_tm_to_secs(const struct tm *t)
|
rtc_tm_to_secs(const struct tm *tm)
|
||||||
{
|
{
|
||||||
uint32 wholeYear;
|
uint32 days;
|
||||||
uint32 time = 0;
|
int year, month;
|
||||||
uint32 i;
|
|
||||||
|
|
||||||
wholeYear = RTC_EPOCHE_BASE_YEAR + t->tm_year;
|
month = tm->tm_mon + 1;
|
||||||
|
year = tm->tm_year + RTC_EPOCH_BASE_YEAR;
|
||||||
|
|
||||||
// ToDo: get rid of these loops and compute the correct value
|
// Reference: Fliegel, H. F. and van Flandern, T. C. (1968).
|
||||||
// i.e. days = (long)(year > 0) + year*365 + --year/4 - year/100 + year/400;
|
// Communications of the ACM, Vol. 11, No. 10 (October, 1968).
|
||||||
// let sSecsPerMonth[] have the values already added up
|
days = tm->tm_mday - 32075 - RTC_EPOCH_JULIAN_DAY
|
||||||
|
+ 1461 * (year + 4800 + (month - 14) / 12) / 4
|
||||||
|
+ 367 * (month - 2 - 12 * ((month - 14) / 12)) / 12
|
||||||
|
- 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4;
|
||||||
|
|
||||||
// Add up the seconds from all years since 1970 that have elapsed.
|
return days * RTC_SECONDS_DAY + tm->tm_hour * 3600 + tm->tm_min * 60
|
||||||
for (i = RTC_EPOCHE_BASE_YEAR; i < wholeYear; ++i) {
|
+ tm->tm_sec;
|
||||||
time += secs_this_year(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add up the seconds from all months passed this year.
|
|
||||||
for (i = 0; i < t->tm_mon && i < 12; ++i)
|
|
||||||
time += sSecsPerMonth[i];
|
|
||||||
|
|
||||||
// Add up the seconds from all days passed this month.
|
|
||||||
if (leap_year(wholeYear) && t->tm_mon >= 2)
|
|
||||||
time += SECONDS_DAY;
|
|
||||||
|
|
||||||
time += (t->tm_mday - 1) * SECONDS_DAY;
|
|
||||||
time += t->tm_hour * 3600;
|
|
||||||
time += t->tm_min * 60;
|
|
||||||
time += t->tm_sec;
|
|
||||||
|
|
||||||
return time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rtc_secs_to_tm(uint32 seconds, struct tm *t)
|
rtc_secs_to_tm(uint32 seconds, struct tm *t)
|
||||||
{
|
{
|
||||||
uint32 wholeYear = RTC_EPOCHE_BASE_YEAR;
|
uint32 year, month, day, l, n;
|
||||||
uint32 secsThisYear;
|
|
||||||
bool keepLooping;
|
|
||||||
bool isLeapYear;
|
|
||||||
int temp;
|
|
||||||
int month;
|
|
||||||
|
|
||||||
keepLooping = 1;
|
// Reference: Fliegel, H. F. and van Flandern, T. C. (1968).
|
||||||
|
// Communications of the ACM, Vol. 11, No. 10 (October, 1968).
|
||||||
|
l = seconds / 86400 + 68569 + RTC_EPOCH_JULIAN_DAY;
|
||||||
|
n = 4 * l / 146097;
|
||||||
|
l = l - (146097 * n + 3) / 4;
|
||||||
|
year = 4000 * (l + 1) / 1461001;
|
||||||
|
l = l - 1461 * year / 4 + 31;
|
||||||
|
month = 80 * l / 2447;
|
||||||
|
day = l - 2447 * month / 80;
|
||||||
|
l = month / 11;
|
||||||
|
month = month + 2 - 12 * l;
|
||||||
|
year = 100 * (n - 49) + year + l;
|
||||||
|
|
||||||
// Determine the current year by starting at 1970 and incrementing whole_year as long as
|
t->tm_mday = day;
|
||||||
// we can keep subtracting secs_this_year from seconds.
|
t->tm_mon = month - 1;
|
||||||
while (keepLooping) {
|
t->tm_year = year - RTC_EPOCH_BASE_YEAR;
|
||||||
secsThisYear = secs_this_year(wholeYear);
|
|
||||||
|
|
||||||
if (seconds >= secsThisYear) {
|
|
||||||
seconds -= secsThisYear;
|
|
||||||
++wholeYear;
|
|
||||||
} else
|
|
||||||
keepLooping = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
t->tm_year = wholeYear - RTC_EPOCHE_BASE_YEAR;
|
|
||||||
|
|
||||||
// Determine the current month
|
|
||||||
month = 0;
|
|
||||||
isLeapYear = leap_year(wholeYear);
|
|
||||||
do {
|
|
||||||
temp = seconds - sSecsPerMonth[month];
|
|
||||||
|
|
||||||
if (isLeapYear && month == 1)
|
|
||||||
temp -= SECONDS_DAY;
|
|
||||||
|
|
||||||
if (temp >= 0) {
|
|
||||||
seconds = temp;
|
|
||||||
++month;
|
|
||||||
}
|
|
||||||
} while (temp >= 0 && month < 12);
|
|
||||||
|
|
||||||
t->tm_mon = month;
|
|
||||||
|
|
||||||
t->tm_mday = seconds / SECONDS_DAY + 1;
|
|
||||||
seconds = seconds % SECONDS_DAY;
|
|
||||||
|
|
||||||
|
seconds = seconds % RTC_SECONDS_DAY;
|
||||||
t->tm_hour = seconds / 3600;
|
t->tm_hour = seconds / 3600;
|
||||||
|
|
||||||
seconds = seconds % 3600;
|
seconds = seconds % 3600;
|
||||||
|
|
||||||
t->tm_min = seconds / 60;
|
t->tm_min = seconds / 60;
|
||||||
seconds = seconds % 60;
|
t->tm_sec = seconds % 60;
|
||||||
|
|
||||||
t->tm_sec = seconds;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user