fix #20390 :get_unix_time_from_datetime and get_date_time_from_unix_time can handle time before year 1970 now

This commit is contained in:
RaphaelHunter 2018-08-09 14:19:19 +08:00 committed by ZhangYakun
parent fed34c3fef
commit 43825dce47
2 changed files with 33 additions and 26 deletions

View file

@ -658,7 +658,7 @@ Dictionary _OS::get_time(bool utc) const {
*
* @return epoch calculated
*/
uint64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
int64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
// Bunch of conversion constants
static const unsigned int SECONDS_PER_MINUTE = 60;
@ -703,13 +703,18 @@ uint64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
// Calculate all the seconds from months past in this year
uint64_t SECONDS_FROM_MONTHS_PAST_THIS_YEAR = DAYS_PAST_THIS_YEAR_TABLE[LEAPYEAR(year)][month - 1] * SECONDS_PER_DAY;
uint64_t SECONDS_FROM_YEARS_PAST = 0;
for (unsigned int iyear = EPOCH_YR; iyear < year; iyear++) {
SECONDS_FROM_YEARS_PAST += YEARSIZE(iyear) * SECONDS_PER_DAY;
int64_t SECONDS_FROM_YEARS_PAST = 0;
if (year >= EPOCH_YR) {
for (unsigned int iyear = EPOCH_YR; iyear < year; iyear++) {
SECONDS_FROM_YEARS_PAST += YEARSIZE(iyear) * SECONDS_PER_DAY;
}
} else {
for (unsigned int iyear = EPOCH_YR - 1; iyear >= year; iyear--) {
SECONDS_FROM_YEARS_PAST -= YEARSIZE(iyear) * SECONDS_PER_DAY;
}
}
uint64_t epoch =
int64_t epoch =
second +
minute * SECONDS_PER_MINUTE +
hour * SECONDS_PER_HOUR +
@ -732,34 +737,36 @@ uint64_t _OS::get_unix_time_from_datetime(Dictionary datetime) const {
*
* @return dictionary of date and time values
*/
Dictionary _OS::get_datetime_from_unix_time(uint64_t unix_time_val) const {
// Just fail if unix time is negative (when interpreted as an int).
// This means the user passed in a negative value by accident
ERR_EXPLAIN("unix_time_val was really huge!" + itos(unix_time_val) + " You probably passed in a negative value!");
ERR_FAIL_COND_V((int64_t)unix_time_val < 0, Dictionary());
Dictionary _OS::get_datetime_from_unix_time(int64_t unix_time_val) const {
OS::Date date;
OS::Time time;
unsigned long dayclock, dayno;
long dayclock, dayno;
int year = EPOCH_YR;
dayclock = (unsigned long)unix_time_val % SECS_DAY;
dayno = (unsigned long)unix_time_val / SECS_DAY;
if (unix_time_val >= 0) {
dayno = unix_time_val / SECS_DAY;
dayclock = unix_time_val % SECS_DAY;
/* day 0 was a thursday */
date.weekday = static_cast<OS::Weekday>((dayno + 4) % 7);
while (dayno >= YEARSIZE(year)) {
dayno -= YEARSIZE(year);
year++;
}
} else {
dayno = (unix_time_val - SECS_DAY + 1) / SECS_DAY;
dayclock = unix_time_val - dayno * SECS_DAY;
date.weekday = static_cast<OS::Weekday>((dayno - 3) % 7 + 7);
do {
year--;
dayno += YEARSIZE(year);
} while (dayno < 0);
}
time.sec = dayclock % 60;
time.min = (dayclock % 3600) / 60;
time.hour = dayclock / 3600;
/* day 0 was a thursday */
date.weekday = static_cast<OS::Weekday>((dayno + 4) % 7);
while (dayno >= YEARSIZE(year)) {
dayno -= YEARSIZE(year);
year++;
}
date.year = year;
size_t imonth = 0;

View file

@ -270,8 +270,8 @@ public:
Dictionary get_date(bool utc) const;
Dictionary get_time(bool utc) const;
Dictionary get_datetime(bool utc) const;
Dictionary get_datetime_from_unix_time(uint64_t unix_time_val) const;
uint64_t get_unix_time_from_datetime(Dictionary datetime) const;
Dictionary get_datetime_from_unix_time(int64_t unix_time_val) const;
int64_t get_unix_time_from_datetime(Dictionary datetime) const;
Dictionary get_time_zone_info() const;
uint64_t get_unix_time() const;
uint64_t get_system_time_secs() const;