I think I've figured it out, and in the process learned a lot more about moving between timestamps and time-strings and extracting the time/date components. Here's a summary of what I found:
- I compared the output from the datepicker UI to the output from a form UI with a Date. The Picker adds the last deployment time of day offset to the picked date. Can't see what the use case is for this, and it's a pain in my application. The form UI always returns the UTC date with no time offset, i.e. midnight.
- Removing the time offset from the Picker seems like a lot of code, unless there's an easier way.
- I guess this is just my lack of javascript knowledge, but it took a while to work out that the Date() function needs to be prefixed with 'new' every time it's used.
My application is using these UI nodes to SELECT data from a SQLITE database, and since the date functions of SQL default to data stored in UTC, the form UI seems much more aligned.
Any feedback or suggestions are welcome.
[{"id":"5a76dea2.0a70c","type":"tab","label":"Date Tests","disabled":false,"info":""},{"id":"d22d96ed.f75f78","type":"ui_date_picker","z":"5a76dea2.0a70c","name":"","label":"date","group":"7d3e55e4.2a3e1c","order":5,"width":0,"height":0,"passthru":true,"topic":"","x":130,"y":140,"wires":[["355ad7d5.9f2168","2218eb0f.eedc04","814d0dcd.9cb78","159a9ea9.69e0f1","a5700c9.daf29f"]]},{"id":"d23ed944.c8c778","type":"ui_text","z":"5a76dea2.0a70c","group":"7d3e55e4.2a3e1c","order":1,"width":0,"height":0,"name":"","label":"Picker Date","format":"{{msg.payload}}","layout":"row-spread","x":610,"y":60,"wires":[]},{"id":"814d0dcd.9cb78","type":"debug","z":"5a76dea2.0a70c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":690,"y":160,"wires":[]},{"id":"2b73dc3f.b3c5c4","type":"ui_form","z":"5a76dea2.0a70c","name":"","label":"","group":"aee7541a.69eb18","order":4,"width":0,"height":0,"options":[{"label":"Date Form","value":"Date_Form","type":"date","required":true,"rows":null}],"formValue":{"Date_Form":""},"payload":"","submit":"submit","cancel":"cancel","topic":"","x":90,"y":400,"wires":[["5c075167.c4849"]]},{"id":"13ada6c6.ac9e39","type":"ui_text","z":"5a76dea2.0a70c","group":"aee7541a.69eb18","order":1,"width":0,"height":0,"name":"","label":"Form Text","format":"{{msg.payload}}","layout":"row-spread","x":530,"y":340,"wires":[]},{"id":"189f3c5b.19a1d4","type":"debug","z":"5a76dea2.0a70c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":770,"y":520,"wires":[]},{"id":"355ad7d5.9f2168","type":"function","z":"5a76dea2.0a70c","name":"Date(msg.payload)","func":"msg.payload = new Date(msg.payload);\nreturn msg;","outputs":1,"noerr":0,"x":370,"y":60,"wires":[["d23ed944.c8c778","814d0dcd.9cb78"]]},{"id":"2218eb0f.eedc04","type":"ui_text","z":"5a76dea2.0a70c","group":"7d3e55e4.2a3e1c","order":1,"width":0,"height":0,"name":"","label":"Picker Timestamp","format":"{{msg.payload}}","layout":"row-left","x":430,"y":120,"wires":[]},{"id":"5c075167.c4849","type":"function","z":"5a76dea2.0a70c","name":"Convert form to Time/Date","func":"var msg2 = {};\nvar msg3 = {};\nmsg2.topic = \"millis\";\n\nvar dateNow = msg.payload.Date_Form;\nmsg.payload = dateNow;\n\nvar timemillis = new Date(dateNow).getTime();\nmsg2.payload = timemillis;\n\nvar localetime = new Date(dateNow).toLocaleTimeString();\nmsg3.payload = localetime;\n\nreturn [msg,msg2,msg3];","outputs":3,"noerr":0,"x":320,"y":400,"wires":[["13ada6c6.ac9e39"],["5dfeadf7.0186c4"],["2c2b4e78.dc53a2"]]},{"id":"5dfeadf7.0186c4","type":"ui_numeric","z":"5a76dea2.0a70c","name":"","label":"Form Timestamp","tooltip":"","group":"aee7541a.69eb18","order":2,"width":0,"height":0,"wrap":false,"passthru":true,"topic":"","format":"{{value}}","min":0,"max":10,"step":1,"x":630,"y":380,"wires":[["189f3c5b.19a1d4"]]},{"id":"159a9ea9.69e0f1","type":"function","z":"5a76dea2.0a70c","name":"Date->Time","func":"var timeofday = new Date(msg.payload).toLocaleTimeString();\nmsg.payload = timeofday;\nreturn msg;","outputs":1,"noerr":0,"x":310,"y":200,"wires":[["b52ba74d.734348"]]},{"id":"b52ba74d.734348","type":"ui_text","z":"5a76dea2.0a70c","group":"7d3e55e4.2a3e1c","order":1,"width":0,"height":0,"name":"","label":"Local Time","format":"{{msg.payload}}","layout":"row-left","x":490,"y":200,"wires":[]},{"id":"2c2b4e78.dc53a2","type":"ui_text","z":"5a76dea2.0a70c","group":"aee7541a.69eb18","order":3,"width":0,"height":0,"name":"","label":"Local Time","format":"{{msg.payload}}","layout":"row-spread","x":630,"y":440,"wires":[]},{"id":"a5700c9.daf29f","type":"function","z":"5a76dea2.0a70c","name":"Adjust date to midnight UTC","func":"//Remove time of day offset from Date Picker output\nvar timestring = new Date(msg.payload);\n var dateplustime = new Date(timestring).getTime();\n var hours = new Date(timestring).getUTCHours();\n var seconds= new Date(timestring).getUTCSeconds();\n var minutes= new Date(timestring).getUTCMinutes();\n var millis= new Date(timestring).getUTCMilliseconds();\n var offset = millis+1000*(seconds+minutes*60+hours*3600);\n var UTCOffsetMins = new Date(timestring).getTimezoneOffset();\n \n\nmsg.payload = dateplustime - offset + (UTCOffsetMins * 60000);\n\nreturn msg;","outputs":1,"noerr":0,"x":360,"y":260,"wires":[["3fe72c3b.93fa94"]]},{"id":"3fe72c3b.93fa94","type":"ui_text","z":"5a76dea2.0a70c","group":"7d3e55e4.2a3e1c","order":3,"width":0,"height":0,"name":"","label":"Adjusted Timestamp","format":"{{msg.payload}}","layout":"row-spread","x":740,"y":260,"wires":[]},{"id":"7d3e55e4.2a3e1c","type":"ui_group","z":"","name":"Date Picker","tab":"7ebce11d.a7c9e","order":1,"disp":true,"width":"6","collapse":false},{"id":"aee7541a.69eb18","type":"ui_group","z":"","name":"Form Date","tab":"7ebce11d.a7c9e","order":2,"disp":true,"width":"6","collapse":false},{"id":"7ebce11d.a7c9e","type":"ui_tab","z":"","name":"Date Tests","icon":"dashboard","order":9,"disabled":false,"hidden":false}]