stefanes / PSTibber

PowerShell module for accessing the Tibber GraphQL API
https://www.powershellgallery.com/packages/PSTibber
MIT License
7 stars 0 forks source link

Add support for datetime in queries #19

Closed trackd closed 1 year ago

trackd commented 1 year ago

Awesome module, use it alot.

I've been missing being able to pass datetime to Get-TibberConsumption.. -Last is not really super user friendly.

I've worked out how to format the graphql query for getting a month.

https://gist.github.com/trackd/7a06b4a3f63e4b8e67696d6dd368a6e4

important bits

[int]$hours = ($date.AddMonths(1) - $date).TotalHours
$DateString = Get-Date -Date $date -Format s
$DateByte = [System.Text.Encoding]::UTF8.GetBytes($DateString)
$base64DateTime = [System.Convert]::ToBase64String($DateByte)
# then in the graph query you can format it like this

consumption(resolution: HOURLY, after: `"$base64DateTime`", first: $hours)

You may use the code as you wish or if you prefer i can work up a PR to integrate into your code. (if it's something you want to add).

stefanes commented 1 year ago

Really great stuff 🎉- I went ahead and added this functionality in PR #20. Please have a look and let me know if this works as you would expect.

trackd commented 1 year ago

Wow, that was super fast! nice 🥇

I did think about one thing, this is more of a choice though. [datetime] assignment without specifying time will set the clock to 00:00:00.

([datetime]'2023-11-12').ToString()
2023-11-12 00:00:00

So if someone does, -From 2023-10-01 -To 2023-10-31 It will not include the last day

Get-TibberConsumption -From 2023-10-29 -To 2023-10-31 | Select-Object -Last 1

from            : 2023-10-30 22:00:00
to              : 2023-10-30 23:00:00
unitPrice       : 0,6278
unitPriceVAT    : 0,12556
consumption     : 3,229
consumptionUnit : kWh
cost            : 2,0271662
currency        : SEK
__typename      : Consumption

that is a bit odd, it's missing an hour.

I might've aliased the -From/-To to something like -Start/-End as well just for ease of use.

stefanes commented 1 year ago

I might've aliased the -From/-To to something like -Start/-End as well just for ease of use.

Done!

stefanes commented 1 year ago

... It will not include the last day

I will think about this some more, but my initial thought is to leave it as it and leave it to the caller to handle. Is it even possible to distinguish between user passing 2023-10-31 and 2023-10-31T00:00:00?

stefanes commented 1 year ago

... that is a bit odd, it's missing an hour.

I got confused about the APIs use of UTC. Fixed in f821fe263bb4bdeda087c8cffbe3b4492ac35530 (I believe, still confused... 🙂).

trackd commented 1 year ago

I will think about this some more, but my initial thought is to leave it as it and leave it to the caller to handle.

Yea i get that, might make the most sense to just mention it in the help or documentation.

Is it even possible to distinguish between user passing 2023-10-31 and 2023-10-31T00:00:00?

This got me a bit curious.. Once it hits a [datetime] cast that info is kind of lost, unless you start peaking around the AST with something like this but that would not be my recommendation ;)

a "simpler" approach if you wanted to be able to detect it would probably be something like this: changing the parameter type to [String]

function Test-dt {
    [cmdletbinding()]
    param(
        [string]
        $dt
    )
    [datetime]$datetime = $dt
    $invariant = $datetime.ToString([System.Globalization.CultureInfo]::InvariantCulture)
    $current = $datetime.ToString([System.Globalization.CultureInfo]::CurrentCulture)
    [PSCustomObject]@{
        String     = $dt
        # Datetime   = $datetime
        Invariant  = $invariant
        current    = $current
        Comparison = $dt -eq $invariant -or $dt -eq $current
    }
}
# comparison fails 
Test-dt (Get-Date).ToShortDateString()
# comparison is sucessful
Test-dt (Get-Date 2023-12-01).ToString('yyyy-MM-dd HH:mm:ss')

# normal datetime format also work with this.
Test-dt (Get-Date)
Test-dt (Get-Date).ToString()

But i would probably just simplify and assume that if time 00:00:00is passed, increase the time to end of the day.

logically it makes the most sense i think, and usually if you ask an api for data between 2 dates it will include those dates. as the -From parameter does not mean after this date (has passed) i think the -To parameter should not mean before this date?

It doesn't matter too much to me, it's fairly easy to handle either.

stefanes commented 1 year ago

... But i would probably just simplify and assume that if time 00:00:00is passed, increase the time to end of the day.

I decided to do just that in f9a9d8e22602f8d3b826409b90f1391c14f35275. I want to keep it simple, and as you say from an API perspective it makes much more sense to have it mean 23:59:59.

It becomes ugly if you really need to pass 00:00:00, but one workaround in this case could be to just add a second (should have no impact on the result), or even just a tick (should definitely have no impact) - this will bypass the check and leave the time as is:

Get-TibberConsumption -From 2023-10-29 -To 2023-10-31 | Select-Object -Last 1  

From                To                  Price    Consumption Cost
----                --                  -----    ----------- ----
2023-10-31 23:00:00 2023-11-01 00:00:00 0,27 SEK 10,89 kWh   2,93 SEK
Get-TibberConsumption -From 2023-10-29 -To 2023-10-31T00:00:01 | Select-Object -Last 1

From                To                  Price    Consumption Cost
----                --                  -----    ----------- ----
2023-10-30 23:00:00 2023-10-31 00:00:00 0,53 SEK 4,04 kWh    2,16 SEK
Get-TibberConsumption -From 2023-10-29 -To ([datetime]'2023-10-31').AddTicks(1) | Select-Object -Last 1    

From                To                  Price    Consumption Cost
----                --                  -----    ----------- ----
2023-10-30 23:00:00 2023-10-31 00:00:00 0,53 SEK 4,04 kWh    2,16 SEK
trackd commented 1 year ago

... that is a bit odd, it's missing an hour.

I got confused about the APIs use of UTC. Fixed in f821fe2 (I believe, still confused... 🙂).

i think you were right before.

# using datetime branch.
Get-TibberConsumption @tibber -From 2023-11-11 -To 2023-11-11 | select -First 1

From                To                  Price    Consumption Cost
----                --                  -----    ----------- ----
2023-11-11 01:00:00 2023-11-11 02:00:00 0,42 SEK 2,02 kWh    0,84 SEK

Get-TibberConsumption @tibber -From 2023-11-11 -To 2023-11-11 | select -Last 1

From                To                  Price    Consumption Cost
----                --                  -----    ----------- ----
2023-11-12 00:00:00 2023-11-12 01:00:00 0,44 SEK 2,66 kWh    1,17 SEK

needs

$From = $From.ToUniversalTime()
[int]$first = ($To.ToUniversalTime() - $From).TotalHours

with those changes im getting the correct hours.

Edit: it might also be that we need to pass timezone, havnt had time to test it

get-date -Format s
2023-11-13T15:06:33
(get-date).ToString("yyyy-MM-ddTHH:mm:ss.fffK")
2023-11-13T15:06:17.598+01:00

tibber api uses

"from": "2023-11-13T00:00:00.000+01:00",
"to": "2023-11-13T01:00:00.000+01:00",
stefanes commented 1 year ago

Reverted back to UTC in 2d2680d9263576e74c50a0fb9fb28bec2ec68e3a.

trackd commented 1 year ago

seem to work fine for me now

Get-TibberConsumption @tibber -From 2023-11-01 -To 2023-11-01 | Select-Object -First 1 -Last 1

From                To                  Price    Consumption Cost
----                --                  -----    ----------- ----
2023-11-01 00:00:00 2023-11-01 01:00:00 0,17 SEK 10,43 kWh   1,75 SEK
2023-11-01 23:00:00 2023-11-02 00:00:00 0,37 SEK 2,00 kWh    0,75 SEK