JsonParseException: unable to parse utc timestamp

Is there something wrong with my timestamp that I'm not seeing?
This is the full resource.json in case it matters:

{
  "scope": "G",
  "version": 2,
  "restricted": false,
  "overridable": true,
  "files": [
    "style.json"
  ],
  "attributes": {
    "lastModification": {
      "actor": "pyro-resource-signature",
      "timestamp": "2024-01-05T02:14:10.53Z"
    },
    "lastModificationSignature": "7e0bf1c8c02ac9bdf9446c3942e9adbb0ec4d16470ee092b9b825edb38d826da"
  }
}

Error Message:

com.inductiveautomation.ignition.common.gson.JsonParseException: unable to parse utc timestamp: 2024-01-05T02:14:10.53Z

at com.inductiveautomation.ignition.common.project.resource.LastModification$GsonAdapter.deserialize(LastModification.java:161)

at com.inductiveautomation.ignition.common.project.resource.LastModification$GsonAdapter.deserialize(LastModification.java:129)

at com.inductiveautomation.ignition.common.gson.internal.bind.TreeTypeAdapter.read(TreeTypeAdapter.java:76)

at com.inductiveautomation.ignition.common.gson.Gson.fromJson(Gson.java:1227)

at com.inductiveautomation.ignition.common.gson.Gson.fromJson(Gson.java:1329)

at com.inductiveautomation.ignition.common.gson.Gson.fromJson(Gson.java:1271)

at com.inductiveautomation.ignition.common.project.resource.LastModification.fromJson(LastModification.java:61)

at java.base/java.util.Optional.map(Unknown Source)

at com.inductiveautomation.ignition.common.project.resource.LastModification.of(LastModification.java:69)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle.lambda$addPendingChangeActorsById$9(ProjectScriptLifecycle.java:648)

at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(Unknown Source)

at java.base/java.util.stream.ReferencePipeline$2$1.accept(Unknown Source)

at java.base/java.util.stream.ReferencePipeline$3$1.accept(Unknown Source)

at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(Unknown Source)

at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)

at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)

at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(Unknown Source)

at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(Unknown Source)

at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)

at java.base/java.util.stream.ReferencePipeline.forEach(Unknown Source)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle.addPendingChangeActorsById(ProjectScriptLifecycle.java:647)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle.addPendingChangeActors(ProjectScriptLifecycle.java:640)

at com.inductiveautomation.ignition.gateway.project.ProjectScriptLifecycle.onResourcesCreated(ProjectScriptLifecycle.java:686)

at com.inductiveautomation.ignition.gateway.project.ProjectLifecycle$LifecycleResourceListener.resourcesCreated(ProjectLifecycle.java:166)

at com.inductiveautomation.ignition.common.project.AbstractProject.notifyResourceListeners(AbstractProject.java:337)

at com.inductiveautomation.ignition.common.project.AbstractProject.updateEffectiveState(AbstractProject.java:153)

at com.inductiveautomation.ignition.common.project.RuntimeProject.applyChange(RuntimeProject.java:274)

at com.inductiveautomation.ignition.gateway.project.ProjectLifecycleFactory$1.lambda$updateOrStartAffectedProjects$5(ProjectLifecycleFactory.java:185)

at java.base/java.util.ArrayList.forEach(Unknown Source)

at com.inductiveautomation.ignition.gateway.project.ProjectLifecycleFactory$1.updateOrStartAffectedProjects(ProjectLifecycleFactory.java:165)

at com.inductiveautomation.ignition.gateway.project.ProjectLifecycleFactory$1.projectUpdated(ProjectLifecycleFactory.java:143)

at com.inductiveautomation.ignition.gateway.project.BaseProjectManager.doProjectUpdatedNotification(BaseProjectManager.java:1055)

at java.base/java.util.ArrayList.forEach(Unknown Source)

at com.inductiveautomation.ignition.gateway.project.BaseProjectManager.lambda$updateProjectFileTree$21(BaseProjectManager.java:960)

at com.inductiveautomation.ignition.common.util.ExecutionQueue$PollAndExecute.run(ExecutionQueue.java:239)

at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)

at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)

at java.base/java.lang.Thread.run(Unknown Source)

Must be the milliseconds.

This is the parser it uses:

    private static final DateFormat ISO_8601_UTC_DATE_FORMAT;

    static {
        ISO_8601_UTC_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        ISO_8601_UTC_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
    }
3 Likes

Ah! Thanks!