Search code examples
iosswiftbluetooth-lowenergydatetime-format

Getting UTC time from BLE device and while converting its showing wrong time


I am using a Bluetooth device data capture project, in that, I have noticed that I am receiving data from Bluetooth devices in the below format

[11, 6, 0, 231, 7, 1, 26, 11, 46, 45, 79, 1, 133, 176, 248, 0, 0]

This have more reference to the field details

Field1: Flags (8bits)
Field2: Sequence number (16bits)
Field3: Date Time (54 bits)
Field4: Time offset (16 bits)
Field5: Units kg/L: (16 bits SFLOAT)
Field6: Units mol/L: (16 bits SFLOAT): NOT PRESENT
Field7: Type: (4bits): 
Field8: Location: (4bit)
Field9: Status: (16bit)

By using the below code I am creating the UTC time

        // First construct the UTC date from the  base time
        let calendar = Calendar.current
        var components = DateComponents()
        
        components.day = newMeasurement[6]
        components.month = newMeasurement[5]
        components.year = ((newMeasurement[4] << 8) | newMeasurement[3])
        
        components.hour = newMeasurement[7]
        components.minute = newMeasurement[8]
        components.second = newMeasurement[9]
        components.timeZone = TimeZone(identifier: "UTC")
        
        let UTCRecord = calendar.date(from: components)

UTC time value looks like 2023-01-26 11:46:45 +0000 and the time offset value in seconds: 20100 and when I convert that into string format I will get: 2023-01-26 17:16:45

Here time shows 17:16:45, but the actual time on the device is 17:21:45

This is how i convert UTCRecord in date format to string format

    let dateString = DateFormatter.localizedString(
            from: UTCRecord,
            dateStyle: .long,
          timeStyle: .medium)`

I really don't have any idea about how this time got wrong.


Solution

  • The calculations are correct. You just need to make use of offset value. Offset is telling us the timeZone of current user. Here is the code sample:

    func convertDate() {
        let gmtTimeString = "2023-01-24 13:40:00" // date string you get from device
    
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        formatter.timeZone = TimeZone(identifier: "UTC")
        guard let date = formatter.date(from: gmtTimeString) else {
            print("can't convert time string")
            return
        }
        let userTimeZone = NSTimeZone.init(forSecondsFromGMT: 20100) //20100 is offset
        formatter.timeZone = userTimeZone as TimeZone            
        let localTimeString = formatter.string(from: date)
        print("date Now:  \(localTimeString)")
    }