非常感谢 cmets,他们让我走上了一条好路。
为了其他遇到此问题的人的利益,这是我使用的代码。
修改模型类:
import java.time.LocalDateTime
class Thing {
public UUID Id
public LocalDateTime CreatedDate
}
Utils 类(还包括 ZonedDateTime 的方法,因为那是我获得原始代码的地方。结果我可以让 LocalDateTime 为我工作。(setDateFormat 是为了支持 Date 对象用于我不需要进行比较的其他模型类,尽管我可以看到自己很快就会弃用所有这些)。
class Utils {
static Gson UtilGson = new GsonBuilder()
.registerTypeAdapter(ZonedDateTime.class, GsonHelper.ZDT_DESERIALIZER)
.registerTypeAdapter(LocalDateTime.class, GsonHelper.LDT_DESERIALIZER)
.registerTypeAdapter(OffsetDateTime.class, GsonHelper.ODT_DESERIALIZER)
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.create();
// From https://stackoverflow.com/a/36418842/276036
static class GsonHelper {
public static final JsonDeserializer<ZonedDateTime> ZDT_DESERIALIZER = new JsonDeserializer<ZonedDateTime>() {
@Override
public ZonedDateTime deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
try {
// if provided as String - '2011-12-03T10:15:30+01:00[Europe/Paris]'
if(jsonPrimitive.isString()){
return ZonedDateTime.parse(jsonPrimitive.getAsString(), DateTimeFormatter.ISO_ZONED_DATE_TIME);
}
// if provided as Long
if(jsonPrimitive.isNumber()){
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(jsonPrimitive.getAsLong()), ZoneId.systemDefault());
}
} catch(RuntimeException e){
throw new JsonParseException("Unable to parse ZonedDateTime", e);
}
throw new JsonParseException("Unable to parse ZonedDateTime");
}
};
public static final JsonDeserializer<LocalDateTime> LDT_DESERIALIZER = new JsonDeserializer<LocalDateTime>() {
@Override
public LocalDateTime deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
try {
// if provided as String - '2011-12-03T10:15:30'
if(jsonPrimitive.isString()){
return LocalDateTime.parse(jsonPrimitive.getAsString(), DateTimeFormatter.ISO_DATE_TIME);
}
// if provided as Long
if(jsonPrimitive.isNumber()){
return LocalDateTime.ofInstant(Instant.ofEpochMilli(jsonPrimitive.getAsLong()), ZoneId.systemDefault());
}
} catch(RuntimeException e){
throw new JsonParseException("Unable to parse LocalDateTime", e);
}
throw new JsonParseException("Unable to parse LocalDateTime");
}
public static final JsonDeserializer<OffsetDateTime> ODT_DESERIALIZER = new JsonDeserializer<OffsetDateTime>() {
@Override
public OffsetDateTime deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive()
try {
// if provided as String - '2011-12-03T10:15:30' (i.e. no timezone information e.g. '2011-12-03T10:15:30+01:00[Europe/Paris]')
// We know our services return UTC dates without specific timezone information so can do this.
// But if, in future we have a different requirement, we'll have to review.
if(jsonPrimitive.isString()){
LocalDateTime localDateTime = LocalDateTime.parse(jsonPrimitive.getAsString());
return localDateTime.atOffset(ZoneOffset.UTC)
}
} catch(RuntimeException e){
throw new JsonParseException("Unable to parse OffsetDateTime", e)
}
throw new JsonParseException("Unable to parse OffsetDateTime")
}
}
};
}
这是进行比较的代码(Spock/Groovy):
// ... first get the JSON text from the REST call
when:
text = response.responseBody
def thing = Utils.UtilGson.fromJson(text, Thing.class)
def now = OffsetDateTime.now(ZoneOffset.UTC)
def aMinuteAgo = now.plusSeconds(-60)
then:
thing.CreatedDate > aMinuteAgo
thing.CreatedDate < now
与运算符进行比较似乎更自然。当我明确将其用于 UTC 时,OffsetDateTime 效果很好。我只使用此模型对服务(它们本身实际上是在 .NET 中实现)执行集成测试,因此这些对象不会在我的测试之外使用。