Using Godot 3.6 on Windows:
How to calculate the ISO week number of a date given the following parameters: day
, month
, year
?
I could not find a way to calculate the week number from the built-in class Time
I've also looked into the Calendar Button Plugin for Godot Engine 3.2.3 repo by Ivan Skodje but could not find any answer or inspiration.
One way I managed to achieve this is by using PowerShell
by using the following self-defined methods:
# Executes the [ script ] in Windows PowerShell
static func execute(script, open_console: bool = false, freeze_loop: bool = true) -> Array:
if OS.get_name() != "Windows":
return []
var output: Array = []
var arguments: PoolStringArray = PoolStringArray([])
match typeof(script):
TYPE_STRING:
arguments.append(script as String)
TYPE_ARRAY, TYPE_STRING_ARRAY:
for line in script:
arguments.append("\n%s" % line)
_:
return []
OS.execute("powershell.exe", arguments, freeze_loop, output, false, open_console)
return output
Inspired by the following answer: Get the ISO 8601 Week of Year of a given date in Powershell
# Returns the ISO week number of the specified date
static func get_iso_week(day: int, month: int, year: int) -> int:
var script: PoolStringArray = PoolStringArray([
"$date = [DateTime] '%d-%d-%d'" % [year, month, day],
("(Get-Culture).Calendar.GetWeekOfYear(($date).AddDays(-[Int]"
+ "(($date).AddDays(-1)).DayOfWeek+3), 2, 1)")
])
var result: Array = execute(script)
if result.empty():
return 0
return result[0].to_int()
Using the above methods ^ the result is accurate and as expected, but the execution time is quite slow especially when calling this function 6 times (once for each week row in a standard calendar), and I don't know how to program a method in PowerShell
that can return a list of all week numbers by the specified month
and year
(this was, only one PowerShell
execution will be performed instead of 6, but I still find this suboptimal)
ChatGPT also failed to find an answer suitable for Godot 3.6 no matter how many times I need to correct it. (Always suggesting classes and methods that do not exist)
The following is based on the Wikipedia article ISO week date:
func get_iso_week_number(day: int, month: int, year: int) -> int:
var start: int = OS.get_unix_time_from_datetime({"year": year, "month": 1, "day": 1})
var current: int = OS.get_unix_time_from_datetime({"year": year, "month": month, "day": day})
var days_since_year_start: int = int((current - start) / 86400.0)
var iso_day_of_year: int = days_since_year_start + 1
var prior_year: int = year - 1
var prior_year_last_weekday : int = last_weekday(prior_year)
var iso_weekday: int = (prior_year_last_weekday + days_since_year_start) % 7 + 1
# warning-ignore:integer_division
var iso_week_number: int = int((iso_day_of_year - iso_weekday + 10) / 7)
if iso_week_number < 1:
iso_week_number = weeks(prior_year)
elif iso_week_number > weeks(year):
iso_week_number = 1
return iso_week_number
func last_weekday(year:int) -> int:
# warning-ignore:integer_division
# warning-ignore:integer_division
# warning-ignore:integer_division
return (year + (year / 4) - (year / 100) + (year / 400)) % 7
func weeks(year:int) -> int:
return 52 + (1 if last_weekday(year) == 4 or last_weekday(year - 1) == 3 else 0)
Note that we use a function which I called last_weekday
which gives us the weekday of December 31 of a given year. First we need it to compute the weekday of arbitrary days, and second for the weeks
function which tells us if a year has 52 or 53 weeks.