Local time in HomeyScript

Is this really the best way to get the local time in HomeyScript or am I missing something?

const sys = await Homey.system.getInfo();
console.log('sys datetime', sys.date)
const datetime = new Date(sys.date)
datetime.setMinutes(datetime.getMinutes() - new Date().getTimezoneOffset())
console.log('local datetime', datetime)

sys datetime 2020-08-07T07:01:36.101Z
local datetime 2020-08-07T09:01:36.101Z

Not really clear what exactly you want? If it’s the current local time in a string:

const time = new Date().toTimeString().split(' ')[0];

I need to do calculations with local time to follow sun position at my location.

Might the Sun Events app be of help?

1 Like

Most of the .get* methods return local values (so new Date().getHours() returns the hours according to local time)

Good tip! I’ll use this app for certain automations. In this case I’m adjusting the color temperature of Hue bulbs throughout the day as if it was always April 16th (a nice long spring day) helping the circadian rhythm keep steady.

Good point! Unfortunately, I’m doing calculations with milisecs.

Here is my script for anyone interested: https://gist.github.com/suhajdab/2f162833369751a07239b6736ddb6d5f

This:

const sunrise = getLocalDatetime(sys.date).setHours(5, 59);

Is the same as this:

const sunrise = new Date(sys.date).setHours(5, 59);

And in fact, I don’t think this actually does what you think it does:

const now = getLocalDatetime(sys.date).getTime();

Because setHours already sets the local time, you don’t have to use getLocalDatetime() to adjust for the timezone: the adjustment that you do now gets reverted by using setHours. However, that reversion doesn’t happen with .getTime(), which means that now will actually be “now + X hours” (where X is the current timezone offset).

To demonstrate the issue, you can add this to your code:

const sunrise = getLocalDatetime(sys.date).setHours(5, 59);
const sunset  = getLocalDatetime(sys.date).setHours(20, 16)
const now     = getLocalDatetime(sys.date).getTime();

const _ = d => new Date(d).toString()

console.log('sunrise', _(sunrise), _(new Date(sys.date).setHours(5, 59)));
console.log('sunset ', _(sunset),  _(new Date(sys.date).setHours(20, 16)));
console.log('now    ', _(now),     _(Date.now()));

For me, this displays the following:

sunrise Fri Aug 07 2020 05:59:20 GMT+0200 (Central European Summer Time) Fri Aug 07 2020 05:59:20 GMT+0200 (Central European Summer Time)
sunset  Fri Aug 07 2020 20:16:20 GMT+0200 (Central European Summer Time) Fri Aug 07 2020 20:16:20 GMT+0200 (Central European Summer Time)
now     Fri Aug 07 2020 13:57:20 GMT+0200 (Central European Summer Time) Fri Aug 07 2020 11:57:20 GMT+0200 (Central European Summer Time)

As you can see, both sunrise and sunset show the exact same strings, regardless of whether getLocalDatetime() gets called or not.

You can also see that “your” value of now is showing a timestamp 2 hours into the future (it’s 11:57 here at the moment).

1 Like

Excellent point! Thanks for taking the time! :slight_smile:
Now it does correctly reflect the progress of the sun for April 16. :+1:

Hey! It seems my local time is broken again in v5. Do you have any ideas on how to fix my script again?

With SDKv3 (part of v5) Athom has decided to break Date functionality so it always returns times using the universal (UTC) timezone, even for methods that are supposed to return local times.

See this issue on Github.

As of yet, Athom hasn’t given a satisfactory answer on how Homeyscript users should deal with this.

You can use this code:

new Date().toLocaleString("nl-NL", {hour12: false, timeZone: "Europe/Amsterdam"})

Use whatever timezone you are living in

1 Like

And then what? How can you perform calculations based on the local time with that?

if you want a date object you need a second line of code:

const now = new Date().toLocaleString("nl-NL", {hour12: false, timeZone: "Europe/Amsterdam"});
**log(new Date(now))**

That’s basically just adding two hours to a UTC timestamp. Calculations will break for timestamps that will cross DST boundaries because UTC doesn’t observe DST, and I’m sure there are other edge cases too (handling dates and times is hard).

Another issue is that the output of toLocaleString('nl-NL') doesn’t yield a parseable date on Node v14 and up. That can also be worked around, but we’re piling up the workarounds here.

All in all not a satisfactory solution in my opinion.

At this moment it’s all we have, i think
Homey is currently using version 12.16

1 Like

Yes, that’s true, but it really bothers me that Athom has implemented this change without considering the implications.

The reason why they implemented this is, as far as I know, to work around possible issues when apps are running and the user changes their timezone. In that case, the running apps will still be running in the “old” timezone, and this may lead to confusion.

But their fix, running all apps in TZ=UTC, is quite honestly terrible, because it now breaks all apps that deal with times/dates and expect the standard (namely that Date objects will return local times/dates unless you explicitly use the UTC-based methods) to apply.

A user will change their Homey’s timezone once, perhaps twice, during the lifetime of the device. I don’t see any problems with either telling the user that changing the timezone may cause certain issues, or to just tell them that Homey needs to reboot after a timezone change. But they haven’t done so, because, I assume, “that’s not user friendly”. Instead, we have broken apps and scripts now, and have to think about workarounds to fix them.

And yes, Homey runs Node v12 now, but I expect them to update to v14 or even v15 in the not so distant future.

2 Likes

Has there been a proper solution to this? I’m experiencing problems in my app because of this!

Extract it from “date human”.