Explorar o código

Fixes #65377: get_datetime_* functions can return wrong values

James %!s(int64=3) %!d(string=hai) anos
pai
achega
0aecfc9254

+ 7 - 8
core/io/resource.cpp

@@ -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;

+ 3 - 7
core/os/os.h

@@ -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;
 

+ 26 - 29
core/os/time.cpp

@@ -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 {

+ 2 - 2
doc/classes/Time.xml

@@ -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">

+ 4 - 17
drivers/unix/os_unix.cpp

@@ -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;
 }
 

+ 1 - 2
drivers/unix/os_unix.h

@@ -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;

+ 7 - 8
platform/android/export/export_plugin.cpp

@@ -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;

+ 3 - 4
platform/linuxbsd/os_linuxbsd.cpp

@@ -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;

+ 14 - 16
platform/macos/export/export_plugin.cpp

@@ -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

+ 16 - 21
platform/uwp/os_uwp.cpp

@@ -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 {

+ 1 - 2
platform/uwp/os_uwp.h

@@ -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;
 

+ 11 - 23
platform/windows/os_windows.cpp

@@ -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 {

+ 1 - 2
platform/windows/os_windows.h

@@ -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;