Inject node - Use local time not UTC

Hey!
Is there any way to make the inject node use the local time and not UTC? While UTC might be fine for some applications, if I want to use timed triggers it's just wrong.

Any way to change this behaviour?

Best regards
Martin

1 Like

Hi - if you want local time timed triggers, then its best to use one of the contrib node timers (maybe bigtimer?)

Good question.

It is not possible, conceptually speaking. The inject node delivers, as default payload, the Unix epoch, which is the number of milliseconds since 1970 Jan 01 00:00:00 UTC . Note the UTC in the end.

If this behavior is changed the node would not be doing its purpose in life.

Now it is possible for instance to create a custom node that injects the local time but since there is already a library that is specialized and state of art for that purpose nobody cares to reinvent the wheel.

Said that, have a look in the node-red-contrib-moment. It is based on the Moment.JS library and, as you wish is time zone aware (also DST/locale aware).

It happens that someone already developed such a custom node.

In fact, it is a set of nodes. The one you may have a look is the time inject of course. I have not tested.

1 Like

Or add a change node like this after the inject node (For the UK +3600000 milliseconds):

3 Likes

Or use the node-red-contrib-moment node to convert to the correct local time including DST & timezone.

But, as always, you may wish to ask whether you are following the best approach. When dealing with time, it is always best to keep all time calculations in UTC until the point of user interaction. That prevents and mixups and generally greatly simplifies processing.

1 Like

One way I got around this problem is to use a function node and put this bit of code in it.

[{"id":"8dcf66c9.6bdd68","type":"function","z":"baf80d2f.6bd538","name":"Time stamp","func":"msg.time = new Date().toLocaleString();\nreturn msg;","outputs":1,"noerr":0,"x":390,"y":3850,"wires":[["d6ba8a8.e508878"]]}]

Put it just after the inject node and all is good.

I really like using the change node when ever possible, but @ghayne 's otherwise elegant solution doesn't deal with daylight saving time (assuming you are in one of the many timezones/countries cursed with DST).

I tend to use the moment node in these cases. i.e. inject the timestamp then transform it with the Moment node.

It would be great to have a Time option in the change and inject nodes (based on moment.js).

Unfortunately, moment.js is rather a beast and is best left to a dedicated node in my opinion. Personally, I wouldn't want moment loaded all the time just in case I needed it once.

I would always choose to store and process date/time data in UTC to avoid DST & timezone errors that plague processing otherwise. Then just convert to local at display/user interaction time.

1 Like

Or use (I just learned):

let gap= new Date().getTimezoneOffset();

Returns the difference between the local time zone and UTC, in minutes.

3 Likes

Thanks for all your replies, I will look into the provided flows and other ways that were mentioned.

I am following the best approach.

We should think about what Node-RED and the time-based inject is used for. If I choose to trigger actions at a very specific point in time, be it an absolute value like "6 o'clock" or be it something that changes from day to day, like sunrise and sunset, UTC is simply not the right approach.

In my example: I want to get the temperature send via Pushover at 6 o'clock, because I will have to get up at 6:15 and would like to know how warm or cold it is in the morning.

This will always happen at 6 o'clock in my local timezone. A timezone were all my devices (including my alarm clock) live and all those devices know when to change times depending on DST and so on and so forth.

So, when I choose to create a node that fires at 6 o'clock, I would expect it to fire at 6 o'clock in the system timezone, just like a cron does and not some crazy "world time" which might be off several hours and I have to do crazy calculations to get the right time.

Taking the approach from @ghayne, I would have to change the scripts two times a year or do fancy calculations to check whether it's already DST or not and add another hour or not.

Don't feel offended, this isn't against you, I just find this behaviour very strange. Node-RED seems to be so carefully built with lots of thought for details and then a timer just completely ignores all time settings on the host system? This is odd, to say at least.

Best regards
Martin

Don't worry, I'm not offended at all :smile:

As you say, your use case needs local time for triggers.

Thankfully, there are plenty of nodes that will help. Many people start with Pete's bigtimer node which should do the job for you. I use that for similar purposes - to set lighting either to fixed times or to some offset of sunset/sunrise.

That would be odd behavior for an end user Timer App to ignore local time -- however, the overriding design philosophy is the "the Editor is not a Dashboard". Just remember that your flows are dealing with the internal workings of the underlying system (NodeJS runtime and Javascript language). So it's appropriate for the inject node to generate a JS timestamp -- which by definition has no timezone component (it is just the number of milliseconds since the epoch).

It appears that you are trying to use a low-level core node to present a location-aware UI experience. Instead, it may be better if you use one of the contrib nodes that others have mentioned, that was designed to handle timezone offsets.

One possible problem I have run into is this: you set some process to run at 1:30 AM (local) every night. Then, when the clock turns back 1 hour at the start of Daylight Savings time, your process ends up running twice that night. This edge case can be avoided by using only Zulu (or GMT) times in your backend logic -- most "timer" apps take your current timezone into account when setting the internal Zulu time value, but that is done by the UI, not the internals.

In general, Julian is right that it is rarely a good design to use anything but internal timestamps in your database and processing logic. Save the conversions from/to local time for the UI framework or application layer.

1 Like

I found this thread because I needed a quick and dirty and lean (i.e. not including any contrib nodes) way to use a switch node on whether it was a weekday or a weekend, which in UTC would be wrong at certain times of day on certain days. I just tossed this function node together in like 5 min, but I think it works, in case anyone finds themselves in the same situation (though if you're in a + zone, check the sign; getTimeZoneOffset() returned 420 for me at -7, so would it be a negative number if you're in a + time zone? idk)

let now = new Date();
let zoneOffset = 
    now.getTimezoneOffset(); // UTC to local, in minutes (is correct for DST)
let nowEpoch = 
    now.getTime(); // or just use msg.payload if coming from inject?
let deoffsetted = 
    new Date(
        nowEpoch - (zoneOffset*60*1000)
    ); // this is now the local clock time in UTC
let dayOfWeek = 
    deoffsetted.getUTCDay(); // which means this is in sync with local
let isWeekday = (dayOfWeek > 0 && dayOfWeek < 6);
msg.payload = {
    now: now,
    nowEpoch: nowEpoch,
    offset: zoneOffset,
    resetDate: deoffsetted,
    isWeekday: isWeekday,
    isWeekend: !isWeekday
}
return msg;
1 Like

This should work to get the day of the week in local time

let dayOfWeek = (new Date()).getDay()

Before anyone is complaining... i know that this topic is from December 2019. But it's the first topic that i found on google when i searched for a solution for the same problem. Since other will also have the same Problem i would like to add some help.

Like @shrickus explained, the inject node is (for some good reason) not respecting the local time zone.

The recommended modules: bigtimer, or sun-position was not helpful for my case. For my usecase the module node-red-contrib-cron-plus seems to be the most useful solution.

It's easy to configure and you can set the designated timezone.

Here an example to trigger something everyday at 10am in my local timezone (Berlin / Germany).

I hope that helps others that also want to shedule events at a certain time in the local timezone.

3 Likes

People who want local time triggers usually have a good reason. Hardly any humans live on UTC.

You can use node-red-contrib-sun-position nodes, there is an enhanced Inject node similar to the build in Node which is based on local time.

The inject node does inject using the local timezone of the node red server. What else would you want it to do?

Actually there are quite a lot of us, at least for part of the year. That is nothing to do with the question though.

Reply went to the wrong person. Sorry. My comment was to someone who hinted that use of local time was somehow a bad practice.