powershelldategodotgdscriptweek-number

(Godot Engine) How to calculate the ISO week number of a specific date?


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)


Solution

  • 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.