Fix CQL tojson timestamp output on negative timestamp values before Gregorian calendar reform in 1582

patch by Stefan Miklosovic; reviewed by Brandon Williams, Berenguer Blasi for CASSANDRA-19566
This commit is contained in:
Stefan Miklosovic 2024-04-17 15:39:34 +02:00
parent f92998190c
commit fba4a85b97
No known key found for this signature in database
GPG Key ID: 32F35CB2F546D93E
4 changed files with 23 additions and 17 deletions

View File

@ -1,4 +1,5 @@
4.0.13
* Fix CQL tojson timestamp output on negative timestamp values before Gregorian calendar reform in 1582 (CASSANDRA-19566)
* Fix few types issues and implement types compatibility tests (CASSANDRA-19479)
* Optionally avoid hint transfer during decommission (CASSANDRA-19525)
* Change logging to TRACE when failing to get peer certificate (CASSANDRA-19508)

View File

@ -80,7 +80,7 @@ public class DateType extends AbstractType<Date>
@Override
public String toJSONString(ByteBuffer buffer, ProtocolVersion protocolVersion)
{
return '"' + TimestampSerializer.getJsonDateFormatter().format(TimestampSerializer.instance.deserialize(buffer)) + '"';
return '"' + TimestampSerializer.getJsonDateFormatter().format(TimestampSerializer.instance.deserialize(buffer).toInstant()) + '"';
}
@Override

View File

@ -102,7 +102,7 @@ public class TimestampType extends TemporalType<Date>
private String toString(Date date)
{
return date != null ? TimestampSerializer.getJsonDateFormatter().format(date) : "";
return date != null ? TimestampSerializer.getJsonDateFormatter().format(date.toInstant()) : "";
}
@Override

View File

@ -22,7 +22,7 @@ import org.apache.cassandra.db.marshal.ValueAccessor;
import org.apache.cassandra.utils.ByteBufferUtil;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.text.Format;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
@ -32,7 +32,6 @@ import java.time.temporal.ChronoField;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;
import java.util.regex.Pattern;
@ -103,23 +102,29 @@ public class TimestampSerializer extends TypeSerializer<Date>
private static final Pattern timestampPattern = Pattern.compile("^-?\\d+$");
private static final FastThreadLocal<SimpleDateFormat> FORMATTER_UTC = new FastThreadLocal<SimpleDateFormat>()
private static final FastThreadLocal<Format> FORMATTER_UTC = new FastThreadLocal<Format>()
{
protected SimpleDateFormat initialValue()
protected java.text.Format initialValue()
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
return sdf;
return new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX")
.parseDefaulting(ChronoField.NANO_OF_DAY, 0)
.toFormatter()
.withZone(ZoneId.of("UTC"))
.toFormat();
}
};
private static final FastThreadLocal<SimpleDateFormat> FORMATTER_TO_JSON = new FastThreadLocal<SimpleDateFormat>()
private static final FastThreadLocal<Format> FORMATTER_TO_JSON = new FastThreadLocal<Format>()
{
protected SimpleDateFormat initialValue()
protected java.text.Format initialValue()
{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSX");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
return sdf;
return new DateTimeFormatterBuilder()
.appendPattern("yyyy-MM-dd HH:mm:ss.SSSX")
.parseDefaulting(ChronoField.NANO_OF_DAY, 0)
.toFormatter()
.withZone(ZoneId.of("UTC"))
.toFormat();
}
};
@ -169,7 +174,7 @@ public class TimestampSerializer extends TypeSerializer<Date>
throw new MarshalException(String.format("Unable to parse a date/time from '%s'", source));
}
public static SimpleDateFormat getJsonDateFormatter()
public static Format getJsonDateFormatter()
{
return FORMATTER_TO_JSON.get();
}
@ -187,7 +192,7 @@ public class TimestampSerializer extends TypeSerializer<Date>
public String toStringUTC(Date value)
{
return value == null ? "" : FORMATTER_UTC.get().format(value);
return value == null ? "" : FORMATTER_UTC.get().format(value.toInstant());
}
public Class<Date> getType()
@ -204,6 +209,6 @@ public class TimestampSerializer extends TypeSerializer<Date>
{
return buffer == null || !buffer.hasRemaining()
? "null"
: FORMATTER_UTC.get().format(deserialize(buffer));
: FORMATTER_UTC.get().format(deserialize(buffer).toInstant());
}
}