ruudverheijden / node-p1-reader

Node.js package for reading and parsing data from the P1 port of a Dutch or Belgian Smart Meter.
MIT License
25 stars 25 forks source link

Timestamp incorrectly parsed in specific edge cases #39

Open FlyByTire opened 7 months ago

FlyByTire commented 7 months ago

The parseTimestamp function is doing 99,9% of the parsing perfectly except it is one month ahead in a few specific edge cases. When a month has 31 days and the next one does not, the parsed timestamp will "rollover" a month ahead more when the current date is at the end of the month (happening 5 times a year at the end of these specific months). This for the duration of the difference to UTC relative to the time zone at the current system time. How to reproduce; example behaviour:

"Raw" timestamp string from p1 meter that is to be parsed: "240201000215W", (the below function should result in the expected return of: "2024-02-01T00:02:15.000Z") where the below instantiated parsedTimestamp at the instantiated moment with new Date() has a "starting" date of "2024-01-31T23:02:15.000Z" (it uses the current system time to set the value it seems, at least in my use case). function in question:

function _parseTimestamp(timestamp) {
    const parsedTimestamp = new Date();

    parsedTimestamp.setUTCFullYear(parseInt(timestamp.substring(0, 2)) + 2000);
    parsedTimestamp.setUTCMonth(parseInt(timestamp.substring(2, 4)) - 1);
    parsedTimestamp.setUTCDate(parseInt(timestamp.substring(4, 6)));
    parsedTimestamp.setUTCHours(parseInt(timestamp.substring(6, 8)));
    parsedTimestamp.setUTCMinutes(parseInt(timestamp.substring(8, 10)));
    parsedTimestamp.setUTCSeconds(parseInt(timestamp.substring(10, 12)));
    parsedTimestamp.setUTCMilliseconds(0);

    return parsedTimestamp.toISOString();

gives a returned date of: "2024-03-01T00:02:15.000Z", one month ahead of the expected "Raw" data.

One proposed solution is to change the order of operations; first set the Miliseconds, then seconds, minutes, hours, date, month and finally the year. This prevents this edge case where the Month rolls over and goes +2 instead of +1 as per P1 expected raw input.

This was an issue for me as i used the p1-reader timestamp as the timestamp to log the data into an influx db instance and i was missing data at the start of February, April, June, September and November. The data was still there, but logged into the database one month ahead of the actual date.