Tutorial: Synchronize time

Tips and Tricks Synchronize time

How to synchronize client with server time

Sometimes you must want the time difference between the user device and the Webcom server. To get this value, you just have to listen to the virtual data node at the "/.info/serverTimeOffset" path (replace “<your-app>” with your actual application identifier):

const offsetRef = new Webcom("<your-app>").child(".info/serverTimeOffset");
var timeOffset=0;
var serverTime;
offsetRef.on("value", snap => {
  timeOffset = snap.val(); // value in milliseconds since Unix Epoch
  console.log("server time offset changed :"+timeOffset);
  serverTime = new Date().getTime() + timeOffset;
  console.log("new server time is "+serverTime);
});

Coming soon!
In the meanwhile, refer to the Android API reference

let datasyncManager = Webcom.defaultApplication.datasyncService.createManager()
datasyncManager.subscribeToStateChange { state in
    guard let backEndTimeOffsetMS = state.connectionState.backEndTimeOffsetMS else {
        return
    }
    print("server time offset changed:", backEndTimeOffsetMS, "ms")
    let backEndTimeOffsetSeconds: TimeInterval = Double(backEndTimeOffsetMS) / 1000
    let backEndDate = Date(timeIntervalSinceNow: backEndTimeOffsetSeconds)
    print("new server time is", backEndDate)
}

Write data with server timestamp

You can use the special variable "Webcom.ServerValue.TIMESTAMP" to store timestamp managed by the Webcom server. This is useful if you want to ensure consistent representation of time in your data. When you read (or listen) values written with this constant, you will receive an integer timestamp (representing the number of milliseconds elapsed since Unix Epoch). You can use the serverTimeOffset described above to display the local time of your client.

For example (replace “<your-app>” with your actual application identifier):

const dataRef = new Webcom("<your-app>").child("mypath");
dataRef.set({
    value: "test",
    time: Webcom.ServerValue.TIMESTAMP
});
dataRef.on("value", snapshot => {
    const data = snapshot.val();
    console.log(`Value '${data.value}' changed at ${Date.new(data.time).toLocaleString()}`);
});

Coming soon!
In the meanwhile, refer to the Android API reference

A WebcomDate value encapsulates a standard Date value. The type also provides a special .backEndCurrentDate instance that represents the Webcom server current date.

You can use the serverTimeOffset described above to display the local time of your client.

struct MyData: Codable {
    let value: String
    let time: WebcomDate
}

let datasyncManager = Webcom.defaultApplication.datasyncService.createManager()
let node = datasyncManager / "mypath"
node? <- MyData(value: "test", time: .backEndCurrentDate)
node?.subscribe(to: .valueChange) { event in
    guard let data: MyData = event.value.decoded() else {
        return
    }
    print("Value '\(data.value)' changed at '\(data.time.value)'")
}

Full example for a simple chat application

In the following code, we use Webcom.ServerValue.TIMESTAMP to store to timestamp of new messages. When we display the message to the user we add the 'timeOffset', so that all messages seems to be timestamped from the local device clock (replace “<your-app>” with your actual application identifier):

const messagesRef = new Webcom('<your-app>');

const offsetRef = messagesRef.child('.info/serverTimeOffset');
var timeOffset=0;
offsetRef.on("value", snap => {
  timeOffset = snap.val();
  console.log("server time offset changed :", timeOffset);
});

// Function called to push message into Webcom
function addMessage(username, message) {
    messagesRef.push({
      text: message,
      name: username,
      time: Webcom.ServerValue.TIMESTAMP
    });
}

messagesRef.on('child_added', snapshot => {
  const data = snapshot.val();
  const message = data.text;
  const username = data.name || "anonymous";
  // Retrieve the timestamp of the message and add the current time offset
  const date = new Date(data.time - timeOffset);

  // Now you just have to append the new message in you page...
});

Coming soon!
In the meanwhile, refer to the Android API reference

struct Message: Codable {
    let username: String
    let message: String
    let date: WebcomDate
}

let app = Webcom.defaultApplication
let manager = app.datasyncService.createManager()
let node = manager.rootNode

// Function called to push message into Webcom
func addMessage(username: String, message: String) {
    node.push(Message(username: username, message: message, date: .backEndCurrentDate))
}

node.subscribe(to: .childAddition) { event in
    guard let message: Message = event.value.decoded() else {
        return
    }
    // Retrieve the device date corresponding to the message date.
    let deviceDate = app.datasyncService.state.connectionState.deviceDate(for: message.date)
    // Now you just have to append the new message in you page...
}