Timezone appears out by 1 hour for Europe/London

I've been struggling to understand why I'm getting the wrong date/time, having read through a large number of threads and guides on this site and many others. I don't like to ask for help until I don't know where to turn, preferring to try and resolve it through other's questions. But I don't know what to do.

It looks like Node-RED thinks Europe/London is +60 minutes from GMT, but that ended on 31 October 2021.

The TimeHelper gets the time from Home Assistant, the time under the node is showing correctly.

The function gets the string from the Helper as "06:06:00". Splits it by the 'colon' and extracts hours and minutes. It then creates a new date beginning from 1970-01-01 with the hours and minutes added on. I've listed the hours and minutes separately to demonstrate that it is collecting the right information, and also the timezone to show it's not reporting correctly.

The Date/Time Formatter is given the string 1970-01-01T07:00 and the timezone 'Europe/London' (currently GMT+0). If I delete either Timezone and leave it as '[determined by system]', moving off the field automatically converts it to 'Europe/London'

The times of the debug log entry (e.g. 01:52:08) are correct for GMT.

If I change the Input/Output Timezone in the Date/Time Formatter to 'ETC/GMT', it outputs it correctly.

If I change the Input/Output Timezone in the Date/Time Formatter to 'Portugal', it outputs it incorrectly, just like London (they're both the same +1 hour).


(Wikipedia)

Is there something obvious I've missed?

Many thanks,

Aubs

.

For convenience, here's my flow:
image

The function is

var Data=msg.payload;
var data=Data.split(":")
var hours=data[0]
var minutes=data[1]

var d= new Date(1970,01,01,hours,minutes);
msg.payload=d.getTime()/1000;
msg.timestamp=d;
msg.hour=hours;
msg.minute=minutes;
msg.timezone=d.getTimezoneOffset();
return msg;

My flow is below if needed:

[{"id":"042d05d87a27157a","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"2672831b.1236ac","type":"inject","z":"042d05d87a27157a","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"60","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":230,"y":220,"wires":[["882eb0d5e5a4c695","eaefd2d6b83f40b7"]]},{"id":"d3ec7afe.0c2968","type":"debug","z":"042d05d87a27157a","name":"Output time","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":630,"y":180,"wires":[]},{"id":"882eb0d5e5a4c695","type":"api-current-state","z":"042d05d87a27157a","name":"TimeHelper","server":"a3a41549.e2ab08","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"input_datetime.bedroom_weekday_morning_start","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":430,"y":120,"wires":[["ce1fac79bac14841"]]},{"id":"ce1fac79bac14841","type":"function","z":"042d05d87a27157a","name":"","func":"var Data=msg.payload;\nvar data=Data.split(\":\")\nvar hours=data[0]\nvar minutes=data[1]\n\nvar d= new Date(1970,01,01,hours,minutes);\nmsg.payload=d.getTime()/1000;\nmsg.timestamp=d;\nmsg.hour=hours;\nmsg.minute=minutes;\nmsg.timezone=d.getTimezoneOffset();\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":460,"y":200,"wires":[["d3ec7afe.0c2968"]]},{"id":"f1176666ceb9c9e8","type":"debug","z":"042d05d87a27157a","name":"OutputDateTime","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":600,"y":260,"wires":[]},{"id":"eaefd2d6b83f40b7","type":"moment","z":"042d05d87a27157a","name":"","topic":"","input":"1970-01-01T07:00","inputType":"str","inTz":"Europe/London","adjAmount":0,"adjType":"days","adjDir":"add","format":"","locale":"C","output":"","outputType":"msg","outTz":"Europe/London","x":440,"y":300,"wires":[["f1176666ceb9c9e8"]]},{"id":"a3a41549.e2ab08","type":"server","name":"Home Assistant","version":2,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30}]

[Admin Edit] backticks moved onto separate lines to correctly format the flow

I couldn't add more images in the initial post...

The debug shows the following with the flow:
image

The debug shows the following if timezone is GMT:
image

The Date/Time Formatter is showing:
image

I've checked Home Assistant (Home Assistant 2021.12.8) docker container is on the correct timezone:
image

I've checked the Node-RED (Node-RED v2.1.4) docker container is on the correct timezone:
image

I've checked my browser (Chrome Version 96.0.4664.110) is reporting the correct timezone:
image

Yeah, it is frustrating when things like that happen.

First off: Welcome. I hope we can help you.

Second:
The code you posted. Not correct.
When you post code (either flow or node) you click the </> button and paste it between the start/end points.

type or paste code here

Like that.

So what does the Date/Time Formatter node give you?
Local time or ZULU time?
I am sure that the timestamp is always ZULU.
So if you want it to be local, you have to do tricks.

We'll get to that after you reply to what I asked.

Thanks for replying Trying_to_learn.

I'm not sure what is wrong with the formatting, I've just checked and both the flow and the function have triple ticks before and after. I'm on my phone at the moment, I'll double check on the computer when I can.

The timezone for Europe/London (my Local time) is GMT which is currently the same as UTC and Zulu.

Interesting. Sorry I live "in the land down under" and we are on summer time. That threw me.
So just to confirm:
With the flow you showed. Press the timestamp (inject) node and tell me what you get in the bottom debug node.
(Declaring the time when you do it)

I've checked the Node-RED (Node-RED v2.1.4) docker container is on the correct timezone

I am not sure if the TZ environment variable affects the time in the container or that it applies to the application, but did you specify the variable ?

Add a debug node showing what is coming out of the TimeHelper node, and post it here.

Changing the Date/Time Formatter node

  • from: Input From >> String >> 1970-01-01T07:00
  • to: Input From >> msg.payload
  • leaving the timezone as Europe/London.

I get both the debug log timestamp and the payload time match as Zulu:

08/01/2022, 08:40:34node: OutputDateTimemsg.payload : string[24]

"2022-01-08T08:40:34.855Z"

Using that timestamp principle, I set the Date/Time Formatter node back to having the String 1970-01-01T07:00 and it gave the incorrect result.

Adding a Z to the end denoting the String is Zulu time, it gives the correct timezone:

So I thought of setting the timezone to GMT:

So it looks like the Date/Time Formatter thinks the time 1970-01-01T07:00 in timezone Europe/London is Zulu+1 and removes 1 hour to make it Zulu.

As it's pushed through from Home Assistant, I don't publish the container, but I've looked at the config via sudo docker inspect addon_a0d7b954_nodered and yes, it appears to be passed correctly:

        "Config": {
            "Hostname": "a0d7b954-nodered",
            "Env": [
                "TZ=Europe/London",
                "LANG=C.UTF-8",
            ],

Thanks Colin - It shows the time String as I expect it to come through:

08/01/2022, 09:33:45node: TimeHeperDebug
msg.payload : string[8]
"06:03:00"
08/01/2022, 09:33:45node: OutputDateTime
msg.payload : string[24]
"1970-01-01T07:00:00.000Z"
08/01/2022, 09:33:45node: Output time
msg : Object
{ _msgid: "b66023d291a9a0ce", payload: 2696580, topic: "", data: object, timestamp: "1970-02-01T05:03:00.000Z" … }

As well as showing us what is coming out of the timehelper node, feed the inject node into a function node containing

msg.payload = new Date().toString()
return msg;

and feed that into a debug node.

The Inject node doesn't pass anything anywhere. It is just a button to get it flowing, except where I was asked to by [Trying_to_learn], but that was for the Date/Time Formatter:

The Function node is only expecting a time String in the format "hh:mm:ss", so pushing the inject node into it wouldn't provide valid input.

I know that, I just want to see what the code I posted shows, it will tell you what time and zone node red thinks it is.

Apologies, I misread your intention as "feed the inject node into the function node", not "into a function node"

Inject timestamp >> Function >> Debug:

08/01/2022, 09:47:02node: 521b2f8b7fc8b738
msg : Object
object
_msgid: "116162c5c52ffe4a"
payload: "Sat Jan 08 2022 09:47:02 GMT+0000 (Greenwich Mean Time)"
topic: ""

.

Sorry, I won't be able to reply until tomorrow now...

We appreciate your enthusiasm, keep it up! That said, for the safety of our community, you’ve reached the maximum number of replies a new user can create on their first day. Please wait 16 hours and you’ll be able to create more replies.

In the meantime, could anyone please try the following flow:

[{"id":"fe82c02aee8c57ea","type":"tab","label":"Flow 1","disabled":false,"info":"","env":[]},{"id":"f6fd2bf71b2e6c85","type":"inject","z":"fe82c02aee8c57ea","name":"Inject","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":150,"y":240,"wires":[["7b567eb414d3f088","e14dbe3b8e36bd2b","a6d16848f7b43ecb","899a290551de28d2"]]},{"id":"7b567eb414d3f088","type":"moment","z":"fe82c02aee8c57ea","name":"Timezone London","topic":"","input":"1970-01-01T07:05","inputType":"str","inTz":"Europe/London","adjAmount":0,"adjType":"days","adjDir":"add","format":"","locale":"C","output":"","outputType":"msg","outTz":"Europe/London","x":390,"y":120,"wires":[["ae3bc64abe9e40aa"]]},{"id":"ae3bc64abe9e40aa","type":"debug","z":"fe82c02aee8c57ea","name":"Timezone London Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":650,"y":120,"wires":[]},{"id":"e14dbe3b8e36bd2b","type":"moment","z":"fe82c02aee8c57ea","name":"Timezone UTC","topic":"","input":"1970-01-01T07:05","inputType":"str","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"","locale":"C","output":"","outputType":"msg","outTz":"ETC/UTC","x":380,"y":200,"wires":[["da53c65ca69eb2ac"]]},{"id":"da53c65ca69eb2ac","type":"debug","z":"fe82c02aee8c57ea","name":"Timezone UTC Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":640,"y":200,"wires":[]},{"id":"a6d16848f7b43ecb","type":"moment","z":"fe82c02aee8c57ea","name":"Timezone GMT","topic":"","input":"1970-01-01T07:05","inputType":"str","inTz":"ETC/GMT","adjAmount":0,"adjType":"days","adjDir":"add","format":"","locale":"C","output":"","outputType":"msg","outTz":"ETC/GMT","x":380,"y":280,"wires":[["4ee12d88dc2f9c77"]]},{"id":"4ee12d88dc2f9c77","type":"debug","z":"fe82c02aee8c57ea","name":"Timezone GMT Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":640,"y":280,"wires":[]},{"id":"0ed43dce3166eb16","type":"debug","z":"fe82c02aee8c57ea","name":"New Date String Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":650,"y":360,"wires":[]},{"id":"899a290551de28d2","type":"function","z":"fe82c02aee8c57ea","name":"New Date String","func":"msg.payload = new Date('1970-01-01T07:05:00.000Z').toString()\nmsg.time = new Date().toString()\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":380,"y":360,"wires":[["0ed43dce3166eb16"]]},{"id":"71091a93018b4231","type":"inject","z":"fe82c02aee8c57ea","name":"Inject","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1970-01-01T07:05","payloadType":"str","x":150,"y":620,"wires":[["e6d15271bfae4bd1","8b724a7358f68935","d42785d1d684a76d","404977a102ec1306"]]},{"id":"e6d15271bfae4bd1","type":"moment","z":"fe82c02aee8c57ea","name":"Timezone London","topic":"","input":"payload","inputType":"msg","inTz":"Europe/London","adjAmount":0,"adjType":"days","adjDir":"add","format":"","locale":"C","output":"","outputType":"msg","outTz":"Europe/London","x":410,"y":460,"wires":[["4617e95b765a562c"]]},{"id":"4617e95b765a562c","type":"debug","z":"fe82c02aee8c57ea","name":"Timezone London Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":650,"y":460,"wires":[]},{"id":"8b724a7358f68935","type":"moment","z":"fe82c02aee8c57ea","name":"Timezone UTC","topic":"","input":"payload","inputType":"msg","inTz":"ETC/UTC","adjAmount":0,"adjType":"days","adjDir":"add","format":"","locale":"C","output":"","outputType":"msg","outTz":"ETC/UTC","x":400,"y":540,"wires":[["6dd889bd2a0ffdd9"]]},{"id":"6dd889bd2a0ffdd9","type":"debug","z":"fe82c02aee8c57ea","name":"Timezone UTC Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":640,"y":540,"wires":[]},{"id":"d42785d1d684a76d","type":"moment","z":"fe82c02aee8c57ea","name":"Timezone GMT","topic":"","input":"payload","inputType":"msg","inTz":"ETC/GMT","adjAmount":0,"adjType":"days","adjDir":"add","format":"","locale":"C","output":"","outputType":"msg","outTz":"ETC/GMT","x":400,"y":620,"wires":[["fd5efddfda147ef4"]]},{"id":"fd5efddfda147ef4","type":"debug","z":"fe82c02aee8c57ea","name":"Timezone GMT Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":640,"y":620,"wires":[]},{"id":"404977a102ec1306","type":"debug","z":"fe82c02aee8c57ea","name":"New Date String Debug","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":650,"y":700,"wires":[]}]

Test examples:

New Date String is:

msg.payload = new Date('1970-01-01T07:05:00.000Z').toString()
msg.time = new Date().toString()
return msg;

I get:

08/01/2022, 10:29:05node: Timezone London Debug
msg.payload : string[24]
"1970-01-01T06:05:00.000Z"
08/01/2022, 10:29:05node: Timezone UTC Debug
msg.payload : string[24]
"1970-01-01T07:05:00.000Z"
08/01/2022, 10:29:05node: Timezone GMT Debug
msg.payload : string[24]
"1970-01-01T07:05:00.000Z"
08/01/2022, 10:29:05node: New Date String Debug
msg : Object
object
_msgid: "024ff737984951a5"
payload: "Thu Jan 01 1970 08:05:00 GMT+0100 (Greenwich Mean Time)"
topic: ""
time: "Sat Jan 08 2022 10:29:05 GMT+0000 (Greenwich Mean Time)"
----------------------------------------
08/01/2022, 10:29:06node: New Date String Debug
msg.payload : string[16]
"1970-01-01T07:05"
08/01/2022, 10:29:06node: Timezone London Debug
msg.payload : string[24]
"1970-01-01T06:05:00.000Z"
08/01/2022, 10:29:06node: Timezone UTC Debug
msg.payload : string[24]
"1970-01-01T07:05:00.000Z"
08/01/2022, 10:29:06node: Timezone GMT Debug
msg.payload : string[24]
"1970-01-01T07:05:00.000Z"

The New Date String node when given a Zulu time returns GMT+1!

Changing the date from 1970-01-01T07:05 to 2022-01-01T07:05 makes it all work correctly (e.g. for the New Date String):

08/01/2022, 10:34:46node: New Date String Debug
msg : Object
object
_msgid: "57b4c13ca840a8db"
payload: "Sat Jan 01 2022 07:05:00 GMT+0000 (Greenwich Mean Time)"
topic: ""
time: "Sat Jan 08 2022 10:34:46 GMT+0000 (Greenwich Mean Time)"

This indicates the timezone Europe/London is reporting incorrectly when presented with a non-Z defined time String for the year 1970.

Javascript appears to think that Jan 1970 was during BST. Experiment with the base year and watch the timezone offset and you will see. I don't know why, but I am sure there is a better way of doing what you want. No time at the moment, will look later.

Can you clarify exactly what you are trying to get out of this? Show us exactly what you want for a given string out of the helper node.

I couldn't post until now, so sorry for the delayed reply.

Our earlier posts overlapped - You're absolutely right and I think I came to the same conclusion in my last reply. It looks like 1970-01-01T00:00:00 (0) to 1971-10-31T01:59:59 (57722399) are all considered BST (GMT+1) (and for other countries too) for some reason, then 1971-10-31T02:00:00 is the first time where it reverts back correctly.

And the answer is here: The epoch was an hour late [dontpanicblog.co.uk]

What I'm trying to achieve is send a time to an ESP device, ideally without a date, so as a base, I am adding the date as 1970-01-01 which makes it consistent and easy to parse once received. I guess I could use another arbitrary date of say 2000-01-01, which is far enough in the past.

I think it's best to do it this way so planning for the future if I decide that it needs to be scheduled on specific dates rather than just the hours, the backbone is already there to process it. e.g. if the value < 86400, it's a time, otherwise it's a date/time ... process accordingly.

Input: "07:10:00" Output: 25800
Input: "09:00:00" Output: 32400
Input: "17:00:00" Output: 61200

I could just do it as the following, but I thought consistency would be better...

var data=msg.payload.split(":")
var hours=data[0]
var minutes=data[1]
var seconds=(hours*60*60)+(minutes*60)
msg.payload=seconds;
return msg;
1 Like

If all you want is seconds since start of day then that is the way to do it. Though you can save a multiply and possibly allow the interpreter to generate more efficient code by using
const seconds=(hours*60+minutes)*60