0

A JSON-API-response contains the following properties:

created_at_timestamp: 1565979486,
timezone: "+01:00",

I am using Moshi and ThreeTenBp to parse the time stamps and prepared the following custom adapters:

class ZonedDateTimeAdapter {

    @FromJson
    fun fromJson(jsonValue: Long?) = jsonValue?.let {
        try {
            ZonedDateTime.ofInstant(Instant.ofEpochSecond(jsonValue), ZoneOffset.UTC) // <---
        } catch (e: DateTimeParseException) {
            println(e.message)
            null
        }
    }

}

As you can see the zone offset is hardcoded here.

class ZonedDateTimeJsonAdapter : JsonAdapter<ZonedDateTime>() {

    private val delegate = ZonedDateTimeAdapter()

    override fun fromJson(reader: JsonReader): ZonedDateTime? {
        val jsonValue = reader.nextLong()
        return delegate.fromJson(jsonValue)
    }

}

...

class ZoneOffsetAdapter {

    @FromJson
    fun fromJson(jsonValue: String?) = jsonValue?.let {
        try {
            ZoneOffset.of(jsonValue)
        } catch (e: DateTimeException) {
            println(e.message)
            null
        }
    }

}

...

class ZoneOffsetJsonAdapter : JsonAdapter<ZoneOffset>() {

    private val delegate = ZoneOffsetAdapter()

    override fun fromJson(reader: JsonReader): ZoneOffset? {
        val jsonValue = reader.nextString()
        return delegate.fromJson(jsonValue)
    }

}

The adapters are registered with Moshi as follows:

Moshi.Builder()
    .add(ZoneOffset::class.java, ZoneOffsetJsonAdapter())
    .add(ZonedDateTime::class.java, ZonedDateTimeJsonAdapter())
    .build()

Parsing the individual fields (created_at_timestamp, timezone) works fine. I want however get rid of the hardcoded zone offset. How can I configure Moshi to fall back on the timezone property when parsing the created_at_timestamp property.

Related

JJD
  • 50,076
  • 60
  • 203
  • 339

1 Answers1

2

For the created_at_timestamp field you should use a type that doesn't have a timezone. This is usually Instant. It identifies a moment in time independent of which timezone it is being interpreted in.

Then in your enclosing type you can define a getter method to combine the instant and zone into one value. The ZonedDateTime.ofInstant method can do this.

JJD
  • 50,076
  • 60
  • 203
  • 339
Jesse Wilson
  • 39,078
  • 8
  • 121
  • 128
  • Thank you! That was the perfect hint. I changed the implementation according to your recommendation, tested it and updated the branch. – JJD Dec 08 '19 at 21:37