Fixes #65377: get_datetime_* functions can return wrong values

This commit is contained in:
James 2022-09-08 13:36:10 +08:00
parent 27e1323473
commit 0aecfc9254
13 changed files with 96 additions and 141 deletions

View file

@ -93,15 +93,14 @@ String Resource::get_path() const {
String Resource::generate_scene_unique_id() {
// Generate a unique enough hash, but still user-readable.
// If it's not unique it does not matter because the saver will try again.
OS::Date date = OS::get_singleton()->get_date();
OS::Time time = OS::get_singleton()->get_time();
OS::DateTime dt = OS::get_singleton()->get_datetime();
uint32_t hash = hash_murmur3_one_32(OS::get_singleton()->get_ticks_usec());
hash = hash_murmur3_one_32(date.year, hash);
hash = hash_murmur3_one_32(date.month, hash);
hash = hash_murmur3_one_32(date.day, hash);
hash = hash_murmur3_one_32(time.hour, hash);
hash = hash_murmur3_one_32(time.minute, hash);
hash = hash_murmur3_one_32(time.second, hash);
hash = hash_murmur3_one_32(dt.year, hash);
hash = hash_murmur3_one_32(dt.month, hash);
hash = hash_murmur3_one_32(dt.day, hash);
hash = hash_murmur3_one_32(dt.hour, hash);
hash = hash_murmur3_one_32(dt.minute, hash);
hash = hash_murmur3_one_32(dt.second, hash);
hash = hash_murmur3_one_32(Math::rand(), hash);
static constexpr uint32_t characters = 5;

View file

@ -202,18 +202,15 @@ public:
MONTH_DECEMBER,
};
struct Date {
struct DateTime {
int64_t year;
Month month;
uint8_t day;
Weekday weekday;
bool dst;
};
struct Time {
uint8_t hour;
uint8_t minute;
uint8_t second;
bool dst;
};
struct TimeZoneInfo {
@ -221,8 +218,7 @@ public:
String name;
};
virtual Date get_date(bool p_utc = false) const = 0;
virtual Time get_time(bool p_utc = false) const = 0;
virtual DateTime get_datetime(bool utc = false) const = 0;
virtual TimeZoneInfo get_time_zone_info() const = 0;
virtual double get_unix_time() const;

View file

@ -324,63 +324,60 @@ String Time::get_offset_string_from_offset_minutes(int64_t p_offset_minutes) con
}
Dictionary Time::get_datetime_dict_from_system(bool p_utc) const {
OS::Date date = OS::get_singleton()->get_date(p_utc);
OS::Time time = OS::get_singleton()->get_time(p_utc);
OS::DateTime dt = OS::get_singleton()->get_datetime(p_utc);
Dictionary datetime;
datetime[YEAR_KEY] = date.year;
datetime[MONTH_KEY] = (uint8_t)date.month;
datetime[DAY_KEY] = date.day;
datetime[WEEKDAY_KEY] = (uint8_t)date.weekday;
datetime[DST_KEY] = date.dst;
datetime[HOUR_KEY] = time.hour;
datetime[MINUTE_KEY] = time.minute;
datetime[SECOND_KEY] = time.second;
datetime[YEAR_KEY] = dt.year;
datetime[MONTH_KEY] = (uint8_t)dt.month;
datetime[DAY_KEY] = dt.day;
datetime[WEEKDAY_KEY] = (uint8_t)dt.weekday;
datetime[HOUR_KEY] = dt.hour;
datetime[MINUTE_KEY] = dt.minute;
datetime[SECOND_KEY] = dt.second;
datetime[DST_KEY] = dt.dst;
return datetime;
}
Dictionary Time::get_date_dict_from_system(bool p_utc) const {
OS::Date date = OS::get_singleton()->get_date(p_utc);
OS::DateTime dt = OS::get_singleton()->get_datetime(p_utc);
Dictionary date_dictionary;
date_dictionary[YEAR_KEY] = date.year;
date_dictionary[MONTH_KEY] = (uint8_t)date.month;
date_dictionary[DAY_KEY] = date.day;
date_dictionary[WEEKDAY_KEY] = (uint8_t)date.weekday;
date_dictionary[DST_KEY] = date.dst;
date_dictionary[YEAR_KEY] = dt.year;
date_dictionary[MONTH_KEY] = (uint8_t)dt.month;
date_dictionary[DAY_KEY] = dt.day;
date_dictionary[WEEKDAY_KEY] = (uint8_t)dt.weekday;
return date_dictionary;
}
Dictionary Time::get_time_dict_from_system(bool p_utc) const {
OS::Time time = OS::get_singleton()->get_time(p_utc);
OS::DateTime dt = OS::get_singleton()->get_datetime(p_utc);
Dictionary time_dictionary;
time_dictionary[HOUR_KEY] = time.hour;
time_dictionary[MINUTE_KEY] = time.minute;
time_dictionary[SECOND_KEY] = time.second;
time_dictionary[HOUR_KEY] = dt.hour;
time_dictionary[MINUTE_KEY] = dt.minute;
time_dictionary[SECOND_KEY] = dt.second;
return time_dictionary;
}
String Time::get_datetime_string_from_system(bool p_utc, bool p_use_space) const {
OS::Date date = OS::get_singleton()->get_date(p_utc);
OS::Time time = OS::get_singleton()->get_time(p_utc);
OS::DateTime dt = OS::get_singleton()->get_datetime(p_utc);
// vformat only supports up to 6 arguments, so we need to split this up into 2 parts.
String timestamp = vformat("%04d-%02d-%02d", date.year, (uint8_t)date.month, date.day);
String timestamp = vformat("%04d-%02d-%02d", dt.year, (uint8_t)dt.month, dt.day);
if (p_use_space) {
timestamp = vformat("%s %02d:%02d:%02d", timestamp, time.hour, time.minute, time.second);
timestamp = vformat("%s %02d:%02d:%02d", timestamp, dt.hour, dt.minute, dt.second);
} else {
timestamp = vformat("%sT%02d:%02d:%02d", timestamp, time.hour, time.minute, time.second);
timestamp = vformat("%sT%02d:%02d:%02d", timestamp, dt.hour, dt.minute, dt.second);
}
return timestamp;
}
String Time::get_date_string_from_system(bool p_utc) const {
OS::Date date = OS::get_singleton()->get_date(p_utc);
OS::DateTime dt = OS::get_singleton()->get_datetime(p_utc);
// Android is picky about the types passed to make Variant, so we need a cast.
return vformat("%04d-%02d-%02d", date.year, (uint8_t)date.month, date.day);
return vformat("%04d-%02d-%02d", dt.year, (uint8_t)dt.month, dt.day);
}
String Time::get_time_string_from_system(bool p_utc) const {
OS::Time time = OS::get_singleton()->get_time(p_utc);
return vformat("%02d:%02d:%02d", time.hour, time.minute, time.second);
OS::DateTime dt = OS::get_singleton()->get_datetime(p_utc);
return vformat("%02d:%02d:%02d", dt.hour, dt.minute, dt.second);
}
Dictionary Time::get_time_zone_from_system() const {

View file

@ -17,7 +17,7 @@
<return type="Dictionary" />
<param index="0" name="utc" type="bool" default="false" />
<description>
Returns the current date as a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]weekday[/code], and [code]dst[/code] (Daylight Savings Time).
Returns the current date as a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], and [code]weekday[/code].
The returned values are in the system's local time when [param utc] is [code]false[/code], otherwise they are in UTC.
</description>
</method>
@ -57,7 +57,7 @@
<return type="Dictionary" />
<param index="0" name="utc" type="bool" default="false" />
<description>
Returns the current date as a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]weekday[/code], [code]hour[/code], [code]minute[/code], and [code]second[/code].
Returns the current date as a dictionary of keys: [code]year[/code], [code]month[/code], [code]day[/code], [code]weekday[/code], [code]hour[/code], [code]minute[/code], [code]second[/code], and [code]dst[/code] (Daylight Savings Time).
</description>
</method>
<method name="get_datetime_dict_from_unix_time" qualifiers="const">

View file

@ -200,7 +200,7 @@ double OS_Unix::get_unix_time() const {
return (double)tv_now.tv_sec + double(tv_now.tv_usec) / 1000000;
}
OS::Date OS_Unix::get_date(bool p_utc) const {
OS::DateTime OS_Unix::get_datetime(bool p_utc) const {
time_t t = time(nullptr);
struct tm lt;
if (p_utc) {
@ -208,7 +208,7 @@ OS::Date OS_Unix::get_date(bool p_utc) const {
} else {
localtime_r(&t, &lt);
}
Date ret;
DateTime ret;
ret.year = 1900 + lt.tm_year;
// Index starting at 1 to match OS_Unix::get_date
// and Windows SYSTEMTIME and tm_mon follows the typical structure
@ -216,24 +216,11 @@ OS::Date OS_Unix::get_date(bool p_utc) const {
ret.month = (Month)(lt.tm_mon + 1);
ret.day = lt.tm_mday;
ret.weekday = (Weekday)lt.tm_wday;
ret.dst = lt.tm_isdst;
return ret;
}
OS::Time OS_Unix::get_time(bool p_utc) const {
time_t t = time(nullptr);
struct tm lt;
if (p_utc) {
gmtime_r(&t, &lt);
} else {
localtime_r(&t, &lt);
}
Time ret;
ret.hour = lt.tm_hour;
ret.minute = lt.tm_min;
ret.second = lt.tm_sec;
get_time_zone_info();
ret.dst = lt.tm_isdst;
return ret;
}

View file

@ -63,8 +63,7 @@ public:
virtual String get_name() const override;
virtual Date get_date(bool p_utc) const override;
virtual Time get_time(bool p_utc) const override;
virtual DateTime get_datetime(bool p_utc) const override;
virtual TimeZoneInfo get_time_zone_info() const override;
virtual double get_unix_time() const override;

View file

@ -569,16 +569,15 @@ bool EditorExportPlatformAndroid::_should_compress_asset(const String &p_path, c
}
zip_fileinfo EditorExportPlatformAndroid::get_zip_fileinfo() {
OS::Time time = OS::get_singleton()->get_time();
OS::Date date = OS::get_singleton()->get_date();
OS::DateTime dt = OS::get_singleton()->get_datetime();
zip_fileinfo zipfi;
zipfi.tmz_date.tm_hour = time.hour;
zipfi.tmz_date.tm_mday = date.day;
zipfi.tmz_date.tm_min = time.minute;
zipfi.tmz_date.tm_mon = date.month - 1; // tm_mon is zero indexed
zipfi.tmz_date.tm_sec = time.second;
zipfi.tmz_date.tm_year = date.year;
zipfi.tmz_date.tm_year = dt.year;
zipfi.tmz_date.tm_mon = dt.month - 1; // tm_mon is zero indexed
zipfi.tmz_date.tm_mday = dt.day;
zipfi.tmz_date.tm_hour = dt.hour;
zipfi.tmz_date.tm_min = dt.minute;
zipfi.tmz_date.tm_sec = dt.second;
zipfi.dosDate = 0;
zipfi.external_fa = 0;
zipfi.internal_fa = 0;

View file

@ -686,10 +686,9 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) {
String renamed_path = path.get_base_dir() + "/" + file_name;
// Generates the .trashinfo file
OS::Date date = OS::get_singleton()->get_date(false);
OS::Time time = OS::get_singleton()->get_time(false);
String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", date.year, (int)date.month, date.day, time.hour, time.minute);
timestamp = vformat("%s%02d", timestamp, time.second); // vformat only supports up to 6 arguments.
OS::DateTime dt = OS::get_singleton()->get_datetime(false);
String timestamp = vformat("%04d-%02d-%02dT%02d:%02d:", dt.year, (int)dt.month, dt.day, dt.hour, dt.minute);
timestamp = vformat("%s%02d", timestamp, dt.second); // vformat only supports up to 6 arguments.
String trash_info = "[Trash Info]\nPath=" + path.uri_encode() + "\nDeletionDate=" + timestamp + "\n";
{
Error err;

View file

@ -1641,16 +1641,15 @@ void EditorExportPlatformMacOS::_zip_folder_recursive(zipFile &p_zip, const Stri
continue;
}
if (da->is_link(f)) {
OS::Time time = OS::get_singleton()->get_time();
OS::Date date = OS::get_singleton()->get_date();
OS::DateTime dt = OS::get_singleton()->get_datetime();
zip_fileinfo zipfi;
zipfi.tmz_date.tm_hour = time.hour;
zipfi.tmz_date.tm_mday = date.day;
zipfi.tmz_date.tm_min = time.minute;
zipfi.tmz_date.tm_mon = date.month - 1; // Note: "tm" month range - 0..11, Godot month range - 1..12, https://www.cplusplus.com/reference/ctime/tm/
zipfi.tmz_date.tm_sec = time.second;
zipfi.tmz_date.tm_year = date.year;
zipfi.tmz_date.tm_year = dt.year;
zipfi.tmz_date.tm_mon = dt.month - 1; // Note: "tm" month range - 0..11, Godot month range - 1..12, https://www.cplusplus.com/reference/ctime/tm/
zipfi.tmz_date.tm_mday = dt.day;
zipfi.tmz_date.tm_hour = dt.hour;
zipfi.tmz_date.tm_min = dt.minute;
zipfi.tmz_date.tm_sec = dt.second;
zipfi.dosDate = 0;
// 0120000: symbolic link type
// 0000755: permissions rwxr-xr-x
@ -1686,16 +1685,15 @@ void EditorExportPlatformMacOS::_zip_folder_recursive(zipFile &p_zip, const Stri
} else {
bool is_executable = (p_folder.ends_with("MacOS") && (f == p_pkg_name)) || p_folder.ends_with("Helpers") || f.ends_with(".command");
OS::Time time = OS::get_singleton()->get_time();
OS::Date date = OS::get_singleton()->get_date();
OS::DateTime dt = OS::get_singleton()->get_datetime();
zip_fileinfo zipfi;
zipfi.tmz_date.tm_hour = time.hour;
zipfi.tmz_date.tm_mday = date.day;
zipfi.tmz_date.tm_min = time.minute;
zipfi.tmz_date.tm_mon = date.month - 1; // Note: "tm" month range - 0..11, Godot month range - 1..12, https://www.cplusplus.com/reference/ctime/tm/
zipfi.tmz_date.tm_sec = time.second;
zipfi.tmz_date.tm_year = date.year;
zipfi.tmz_date.tm_year = dt.year;
zipfi.tmz_date.tm_mon = dt.month - 1; // Note: "tm" month range - 0..11, Godot month range - 1..12, https://www.cplusplus.com/reference/ctime/tm/
zipfi.tmz_date.tm_mday = dt.day;
zipfi.tmz_date.tm_hour = dt.hour;
zipfi.tmz_date.tm_min = dt.minute;
zipfi.tmz_date.tm_sec = dt.second;
zipfi.dosDate = 0;
// 0100000: regular file type
// 0000755: permissions rwxr-xr-x

View file

@ -444,7 +444,7 @@ String OS_UWP::get_name() const {
return "UWP";
}
OS::Date OS_UWP::get_date(bool p_utc) const {
OS::DateTime OS_UWP::get_datetime(bool p_utc) const {
SYSTEMTIME systemtime;
if (p_utc) {
GetSystemTime(&systemtime);
@ -452,28 +452,23 @@ OS::Date OS_UWP::get_date(bool p_utc) const {
GetLocalTime(&systemtime);
}
Date date;
date.day = systemtime.wDay;
date.month = Month(systemtime.wMonth);
date.weekday = Weekday(systemtime.wDayOfWeek);
date.year = systemtime.wYear;
date.dst = false;
return date;
}
OS::Time OS_UWP::get_time(bool p_utc) const {
SYSTEMTIME systemtime;
if (p_utc) {
GetSystemTime(&systemtime);
} else {
GetLocalTime(&systemtime);
//Get DST information from Windows, but only if p_utc is false.
TIME_ZONE_INFORMATION info;
bool daylight = false;
if (!p_utc && GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT) {
daylight = true;
}
Time time;
time.hour = systemtime.wHour;
time.min = systemtime.wMinute;
time.sec = systemtime.wSecond;
return time;
DateTime dt;
dt.year = systemtime.wYear;
dt.month = Month(systemtime.wMonth);
dt.day = systemtime.wDay;
dt.weekday = Weekday(systemtime.wDayOfWeek);
dt.hour = systemtime.wHour;
dt.minute = systemtime.wMinute;
dt.second = systemtime.wSecond;
dt.dst = daylight;
return dt;
}
OS::TimeZoneInfo OS_UWP::get_time_zone_info() const {

View file

@ -184,8 +184,7 @@ public:
virtual String get_name() const;
virtual Date get_date(bool p_utc) const;
virtual Time get_time(bool p_utc) const;
virtual DateTime get_datetime(bool p_utc) const;
virtual TimeZoneInfo get_time_zone_info() const;
virtual uint64_t get_unix_time() const;

View file

@ -290,7 +290,7 @@ String OS_Windows::get_name() const {
return "Windows";
}
OS::Date OS_Windows::get_date(bool p_utc) const {
OS::DateTime OS_Windows::get_datetime(bool p_utc) const {
SYSTEMTIME systemtime;
if (p_utc) {
GetSystemTime(&systemtime);
@ -305,28 +305,16 @@ OS::Date OS_Windows::get_date(bool p_utc) const {
daylight = true;
}
Date date;
date.day = systemtime.wDay;
date.month = Month(systemtime.wMonth);
date.weekday = Weekday(systemtime.wDayOfWeek);
date.year = systemtime.wYear;
date.dst = daylight;
return date;
}
OS::Time OS_Windows::get_time(bool p_utc) const {
SYSTEMTIME systemtime;
if (p_utc) {
GetSystemTime(&systemtime);
} else {
GetLocalTime(&systemtime);
}
Time time;
time.hour = systemtime.wHour;
time.minute = systemtime.wMinute;
time.second = systemtime.wSecond;
return time;
DateTime dt;
dt.year = systemtime.wYear;
dt.month = Month(systemtime.wMonth);
dt.day = systemtime.wDay;
dt.weekday = Weekday(systemtime.wDayOfWeek);
dt.hour = systemtime.wHour;
dt.minute = systemtime.wMinute;
dt.second = systemtime.wSecond;
dt.dst = daylight;
return dt;
}
OS::TimeZoneInfo OS_Windows::get_time_zone_info() const {

View file

@ -146,8 +146,7 @@ public:
virtual void initialize_joypads() override {}
virtual Date get_date(bool p_utc) const override;
virtual Time get_time(bool p_utc) const override;
virtual DateTime get_datetime(bool p_utc) const override;
virtual TimeZoneInfo get_time_zone_info() const override;
virtual double get_unix_time() const override;