Skip to content

Issue with ZonedDateTime Handling in Couchbase SDK #2056

Closed
@jessaardithya

Description

@jessaardithya

We are encountering challenges with converting ZonedDateTime fields when using the Couchbase SDK. Our application relies on Java’s standard ZonedDateTime type for several temporal fields, as it retains not only the date and time, but also the associated time zone and offset. This level of precision is essential to ensure a consistent user experience, as well as for auditing and business logic purposes.

For further context :

Preserving Java’s standard ZonedDateTime type-2025052409201526 (1).pdf

Then we tried to solve it, After reviewing, the converters should use CouchbaseDocument (instead of JsonObject). That’s what Couchbase uses internally when de/serializing. Adjust the converters as necessary to achieve the desired result. This also shows overriding additionalConverters (instead of overriding customConversions()).

@Override
	protected void additionalConverters(List<Object> converters) {
		converters.add(new ZonedDateTimeToCouchbaseDocumentConverter());
		converters.add(new CouchbaseDocumentToZonedDateTimeConverter());
	}

	@WritingConverter
	public class ZonedDateTimeToCouchbaseDocumentConverter implements Converter<ZonedDateTime, CouchbaseDocument> {
		@Override     public CouchbaseDocument convert(ZonedDateTime source) {
			CouchbaseDocument obj = new CouchbaseDocument();
			// Adjust construction of document as needed
			obj.put("dateTime", source.toOffsetDateTime().toString());
			obj.put("offset", source.getOffset().toString());
			obj.put("zone", source.getZone().toString());
			return obj;

		}
	}

	@ReadingConverter
	public class CouchbaseDocumentToZonedDateTimeConverter implements Converter<CouchbaseDocument, ZonedDateTime> {
		@Override     public ZonedDateTime convert(CouchbaseDocument source) {
		    // Adjust construction of ZonedDateTime as needed. This implementation ignores offset and zone.
			ZonedDateTime obj = ZonedDateTime.parse(source.get("dateTime").toString());
			return obj;
		}
	}

	
	public static class ZDTEntity  extends BaseEntity {
		public ZonedDateTime zdt;

		public ZDTEntity(ZonedDateTime zdt) {
			this.zdt = zdt;
		}

	}

	@Test
	void writesZonedDateTime() {
		CouchbaseDocument converted = new CouchbaseDocument();
		ZDTEntity entity = new ZDTEntity(ZonedDateTime.parse("2025-01-31T10:20:49Z"));
		customConverter.write(entity, converted);
		Map<String, Object> result = converted.export();
		Map<String,Object> attr0 = (Map<String,Object>)result.get("zdt");
		assertThat(attr0.get("dateTime")).isEqualTo(entity.zdt.toOffsetDateTime().toString());
		assertThat(attr0.get("offset")).isEqualTo(entity.zdt.getOffset().toString());
		assertThat(attr0.get("zone")).isEqualTo(entity.zdt.getZone().toString());
		assertThat(converted.getId()).isEqualTo(BaseEntity.ID);
		System.err.println(attr0);
	}

{dateTime=2025-01-31T10:20:49Z, offset=Z, zone=Z}


	@Test
	void readsZonedDateTime() {
		CouchbaseDocument source = new CouchbaseDocument();
		source.put("t", StringEntity.class.getName());
		CouchbaseDocument attr0 = new CouchbaseDocument();
		ZonedDateTime zdt = ZonedDateTime.parse("2025-01-31T10:20:49Z");;
		attr0.put("dateTime", zdt.toOffsetDateTime());
		attr0.put("offset", zdt.getOffset().toString());
		attr0.put("zone", zdt.getZone());
		source.put("zdt", attr0);
		ZDTEntity converted = customConverter.read(ZDTEntity.class, source);
		assertThat(converted.zdt.toOffsetDateTime()).isEqualTo(zdt.toOffsetDateTime());
		System.err.println(converted.zdt);
	}

But still got an error :

Image

Actually, The code above looks almost correct for both the reading and writing converters — what’s left is just how to register them in the Couchbase configuration. it’s the section in the Couchbase config where we register the reading and writing converters that have already been defined.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions