From 3ec925210aa0a353460d12b5ab1e10214db79a13 Mon Sep 17 00:00:00 2001
From: Vasyl Khrystiuk
Date: Mon, 8 Apr 2024 01:36:52 +0300
Subject: [PATCH] fix for #298 1) change rendering - now temporal accessors are
rendered via pattern without conversion to zoned date time, so Instant is
safe now 2) add more patterns support
---
src/main/java/liqp/LValue.java | 25 ++-
src/main/java/liqp/TemplateParser.java | 3 +
src/main/java/liqp/filters/Date.java | 3 +-
src/main/java/liqp/filters/date/Parser.java | 144 ++++++++++++------
src/main/java/liqp/nodes/BlockNode.java | 10 +-
.../liqp/nodes/ComparingExpressionNode.java | 16 +-
src/test/java/liqp/filters/DateTest.java | 8 +
7 files changed, 148 insertions(+), 61 deletions(-)
diff --git a/src/main/java/liqp/LValue.java b/src/main/java/liqp/LValue.java
index b09ad898..9e91fb84 100644
--- a/src/main/java/liqp/LValue.java
+++ b/src/main/java/liqp/LValue.java
@@ -7,6 +7,7 @@
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
+import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -194,7 +195,23 @@ public static Object[] temporalAsArray(ZonedDateTime time) {
return new Object[]{sec, min, hour, day, month, year, wday, yday, isdst, zone};
}
- public static ZonedDateTime asTemporal(Object value, TemplateContext context) {
+ /**
+ * This one keeps an original temporal type as is, while `asRubyDate` converts it to ZonedDateTime.
+ */
+ public static TemporalAccessor asTemporal(Object value, TemplateContext context) {
+ ZonedDateTime time = ZonedDateTime.now();
+ if (value instanceof TemporalAccessor) {
+ return (TemporalAccessor) value;
+ } else if (CustomDateFormatRegistry.isCustomDateType(value)) {
+ time = CustomDateFormatRegistry.getFromCustomType(value);
+ }
+ return time;
+ }
+
+ /**
+ * Ruby have a single date type, and its equivalent is ZonedDateTime.
+ */
+ public static ZonedDateTime asRubyDate(Object value, TemplateContext context) {
ZonedDateTime time = ZonedDateTime.now();
if (value instanceof TemporalAccessor) {
time = getZonedDateTimeFromTemporalAccessor((TemporalAccessor) value, context.getParser().defaultTimeZone);
@@ -306,7 +323,7 @@ public String asString(Object value, TemplateContext context) {
}
if (isTemporal(value)) {
- ZonedDateTime time = asTemporal(value, context);
+ ZonedDateTime time = asRubyDate(value, context);
return rubyDateTimeFormat.format(time);
}
@@ -339,7 +356,7 @@ public Object asAppendableObject(Object value, TemplateContext context) {
}
if (isTemporal(value)) {
- ZonedDateTime time = asTemporal(value, context);
+ ZonedDateTime time = asRubyDate(value, context);
return rubyDateTimeFormat.format(time);
}
@@ -380,7 +397,7 @@ public boolean isArray(Object value) {
* @return true iff `value` is a whole number (Integer or Long).
*/
public boolean isInteger(Object value) {
- return value != null && (value instanceof Long || value instanceof Integer);
+ return (value instanceof Long || value instanceof Integer);
}
/**
diff --git a/src/main/java/liqp/TemplateParser.java b/src/main/java/liqp/TemplateParser.java
index b6d954d5..df078d00 100644
--- a/src/main/java/liqp/TemplateParser.java
+++ b/src/main/java/liqp/TemplateParser.java
@@ -78,6 +78,9 @@ public enum ErrorMode {
public final boolean showExceptionsFromInclude;
public final TemplateParser.EvaluateMode evaluateMode;
public final Locale locale;
+ /**
+ * Never null, if empty - system default timezone is used.
+ */
public final ZoneId defaultTimeZone;
private final RenderTransformer renderTransformer;
private final Consumer