nightscout / nightguard

iOS and WatchOS Client for the Nightscout CGM System
GNU Affero General Public License v3.0
243 stars 159 forks source link

Date of treatment for "CGM Sensor Insert" or "Pump Site Change" differs with 1h in CET #264

Closed Joerg-Schoemer closed 11 months ago

Joerg-Schoemer commented 1 year ago

In CEST everything worked fine, now in CET it is 1h to earlier calculated in UTC

dhermanns commented 1 year ago

Hi! You mean you set the time with nightguard and afterwards it differs by one hour?

Joerg-Schoemer commented 1 year ago

Yes, when I enter an event at 16.00h in Nightguard it appears at 15.00h in Nightscout

dhermanns commented 1 year ago

You should check your settings on your server side. Can't reproduce this here with my Setup and CET timezone.

Joerg-Schoemer commented 1 year ago

The event date should be in UTC (string with Z at the end of the date). What setting can be wrong on the server to miss interpret the date?

dhermanns commented 1 year ago

I'm not a cgm-remote-monitor expert. So maybe you ask this there. From a nightguard perspective, I'm creating Global (UTC) Time for the timestamp here:

https://github.com/nightscout/nightguard/blob/master/nightguard/DateExtension.swift#L70

Looks ok to me.

Joerg-Schoemer commented 12 months ago

Hi Dirk,

I've added a test to see what happens.

final class DateExtensionTest: XCTestCase {

    override func setUpWithError() throws {
        // Put setup code here. This method is called before the invocation of each test method in the class.
    }

    override func tearDownWithError() throws {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
    }

    func testExample() throws {

        let now = Date.now

        let gmt = now.toGlobalTime()

        var utcIsoFormatter = Date.ISO8601FormatStyle()
        // utcIsoFormatter.timeZone = TimeZone.gmt

        print("\(now.formatted(utcIsoFormatter)) \(gmt.formatted(utcIsoFormatter))")

        var localIsoFormatter = Date.ISO8601FormatStyle()
        localIsoFormatter.timeZone = TimeZone.current

        print("\(now.formatted(localIsoFormatter)) \(gmt.formatted(localIsoFormatter))")

        XCTAssert(gmt != now)
    }

    func testPerformanceExample() throws {
        // This is an example of a performance test case.
        self.measure {
            // Put the code you want to measure the time of here.
        }
    }

}

when I run the test now is already in the TimeZone UTC. So when subtracting the TimeZone.current difference, which is 1h, the "GlobalTime" is GMT-1

A calculation is not needed, the formatter should be configured for the desired TimeZone.

Joerg-Schoemer commented 11 months ago

Hi Dirk,

after hours spend on created_at I've found the bug

REST API treatment created [
{
    eventType: 'Site Change',
    enteredBy: 'nightguard',
    created_at: '2023-12-04T18:10:00.000Z',
    mills: 1701709800000,
    utcOffset: 0,
    _id: 656e3bf536b9019ceaa8d8da
}
]

created_at looks good 👍🏻 but when creating a date from mills in JavaScript it is interpreted as:

date = new Date(1701709800000)
Mon Dec 04 2023 18:10:00 GMT+0100

converted to UTC 2023-12-04T17:10:00Z is one hour to early 👎🏻

The bug is in the calculation of the mills.