Reputation: 2358
I'm working on a spring-boot
WebApp project with clients located in different timezones, eventually in different countries. I'm storing the date/time in UTC in the database. I'm also using spring-mvc
, spring-data-jpa
with hibernate
and the Java time API
(Java 8). One of the requirements is to show to the users the local date time and format accordingly to their locale (from the user profile).
My question is what is the best place to make it as transparent as possible to avoid polluting the code everywhere with date/time conversions. The first thing that comes to my mind is to use a Filter to intercept the request/response and make the conversion getting the location from a ThreadLocal object associated with the current user, but on this point, the data is still too raw. Another alternative is to use an interceptor with hibernate and make the conversion before saving and after reading.
I appreciate any suggestion and if possible the eventual advantages and drawbacks of the specified solution.
Upvotes: 0
Views: 1237
Reputation: 5474
Using interceptor or filter sounds overkill to me. Checking for each request for datetime field that can be converted to user timezone is too much when you only want to convert certain datetime field to user specific time zone.
Easier approach is to specify a custom JsonSerializer
and JsonDeserializer
when de/serializing your java objects to/from the client side. Since you are using Java 8, you can use ZonedDateTime to store DateTime and Zone together in one field.
It is a common practice to store userTimeZone in the session. The custom serializers need to be spring beans so that you can inject the session then grab the userTimeZone saved in it.
Sharing you some psuecode
The DTO :
public class TheDTO {
@JsonSerialize(using = UserTimeZoneAwareSerializer.class)
@JsonDeserialize(using = UserTimeZoneAwareDeserializer.class)
private ZonedDateTime dateTime;
public ZonedDateTime getDateTime() {
return dateTime;
}
public void setDateTime(ZonedDateTime dateTime) {
this.dateTime = dateTime;
}
}
The serializer, from your handler to the client side :
@Component
public class UserTimeZoneAwareSerializer extends JsonSerializer<ZonedDateTime> {
@Autowired
private HttpSession httpSession;
@Override
public void serialize(ZonedDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
// Grab the userTimeZone from the session then convert from UTC to userTimeZone
gen.writeObject(/**/);
}
}
The deserializer, from the client side to your handler :
@Component
public class UserTimeZoneAwareDeserializer extends JsonDeserializer<ZonedDateTime> {
@Autowired
private HttpSession httpSession;
@Override
public ZonedDateTime deserialize(JsonParser p, DeserializationContext ctxt)
// Grab the userTimeZone then convert from userTimeZone to UTC
// ...
}
}
This way, you can easily annotate a ZonedDateTime
field which you want to be aware of the users timezone.
Upvotes: 1