diff --git a/lang/c++/impl/Compiler.cc b/lang/c++/impl/Compiler.cc index 3b287c9eeb0..2599f7cc664 100644 --- a/lang/c++/impl/Compiler.cc +++ b/lang/c++/impl/Compiler.cc @@ -369,6 +369,10 @@ static LogicalType makeLogicalType(const Entity &e, const Object &m) { t = LogicalType::TIMESTAMP_MILLIS; else if (typeField == "timestamp-micros") t = LogicalType::TIMESTAMP_MICROS; + else if (typeField == "local-timestamp-millis") + t = LogicalType::LOCAL_TIMESTAMP_MILLIS; + else if (typeField == "local-timestamp-micros") + t = LogicalType::LOCAL_TIMESTAMP_MICROS; else if (typeField == "duration") t = LogicalType::DURATION; else if (typeField == "uuid") diff --git a/lang/c++/impl/LogicalType.cc b/lang/c++/impl/LogicalType.cc index 5e03a313d8f..a7260accd16 100644 --- a/lang/c++/impl/LogicalType.cc +++ b/lang/c++/impl/LogicalType.cc @@ -71,6 +71,12 @@ void LogicalType::printJson(std::ostream &os) const { case TIMESTAMP_MICROS: os << R"("logicalType": "timestamp-micros")"; break; + case LOCAL_TIMESTAMP_MILLIS: + os << R"("logicalType": "local-timestamp-millis")"; + break; + case LOCAL_TIMESTAMP_MICROS: + os << R"("logicalType": "local-timestamp-micros")"; + break; case DURATION: os << R"("logicalType": "duration")"; break; diff --git a/lang/c++/impl/Node.cc b/lang/c++/impl/Node.cc index 14ce6ecf05b..9f641e2956a 100644 --- a/lang/c++/impl/Node.cc +++ b/lang/c++/impl/Node.cc @@ -189,6 +189,18 @@ void Node::setLogicalType(LogicalType logicalType) { "LONG type"); } break; + case LogicalType::LOCAL_TIMESTAMP_MILLIS: + if (type_ != AVRO_LONG) { + throw Exception("LOCAL-TIMESTAMP-MILLIS logical type can only annotate " + "LONG type"); + } + break; + case LogicalType::LOCAL_TIMESTAMP_MICROS: + if (type_ != AVRO_LONG) { + throw Exception("LOCAL-TIMESTAMP-MICROS logical type can only annotate " + "LONG type"); + } + break; case LogicalType::DURATION: if (type_ != AVRO_FIXED || fixedSize() != 12) { throw Exception("DURATION logical type can only annotate " diff --git a/lang/c++/include/avro/LogicalType.hh b/lang/c++/include/avro/LogicalType.hh index ff430fd086a..3156f164e1f 100644 --- a/lang/c++/include/avro/LogicalType.hh +++ b/lang/c++/include/avro/LogicalType.hh @@ -35,6 +35,8 @@ public: TIME_MICROS, TIMESTAMP_MILLIS, TIMESTAMP_MICROS, + LOCAL_TIMESTAMP_MILLIS, + LOCAL_TIMESTAMP_MICROS, DURATION, UUID }; diff --git a/lang/c++/include/avro/Node.hh b/lang/c++/include/avro/Node.hh index f76078b052b..e1a8e660f4d 100644 --- a/lang/c++/include/avro/Node.hh +++ b/lang/c++/include/avro/Node.hh @@ -25,6 +25,7 @@ #include #include #include +#include #include "CustomAttributes.hh" #include "Exception.hh" diff --git a/lang/c++/test/SchemaTests.cc b/lang/c++/test/SchemaTests.cc index 543f9e05087..f57cfd1352b 100644 --- a/lang/c++/test/SchemaTests.cc +++ b/lang/c++/test/SchemaTests.cc @@ -217,6 +217,8 @@ const char *roundTripSchemas[] = { R"({"type":"long","logicalType":"time-micros"})", R"({"type":"long","logicalType":"timestamp-millis"})", R"({"type":"long","logicalType":"timestamp-micros"})", + R"({"type":"long","logicalType":"local-timestamp-millis"})", + R"({"type":"long","logicalType":"local-timestamp-micros"})", R"({"type":"fixed","name":"test","size":12,"logicalType":"duration"})", R"({"type":"string","logicalType":"uuid"})", @@ -242,6 +244,8 @@ const char *malformedLogicalTypes[] = { R"({"type":"string","logicalType":"time-micros"})", R"({"type":"string","logicalType":"timestamp-millis"})", R"({"type":"string","logicalType":"timestamp-micros"})", + R"({"type":"string","logicalType":"local-timestamp-millis"})", + R"({"type":"string","logicalType":"local-timestamp-micros"})", R"({"type":"string","logicalType":"duration"})", R"({"type":"long","logicalType":"uuid"})", // Missing the required field 'precision'. @@ -356,6 +360,12 @@ static void testLogicalTypes() { const char *timestampMicrosType = "{\n\ \"type\": \"long\", \"logicalType\": \"timestamp-micros\"\n\ }"; + const char *localTimestampMillisType = "{\n\ + \"type\": \"long\", \"logicalType\": \"local-timestamp-millis\"\n\ + }"; + const char *localTimestampMicrosType = "{\n\ + \"type\": \"long\", \"logicalType\": \"local-timestamp-micros\"\n\ + }"; const char *durationType = "{\n\ \"type\": \"fixed\",\n\ \"size\": 12,\n\ @@ -436,6 +446,24 @@ static void testLogicalTypes() { GenericDatum datum(schema); BOOST_CHECK(datum.logicalType().type() == LogicalType::TIMESTAMP_MICROS); } + { + BOOST_TEST_CHECKPOINT(localTimestampMillisType); + ValidSchema schema = compileJsonSchemaFromString(localTimestampMillisType); + BOOST_CHECK(schema.root()->type() == AVRO_LONG); + LogicalType logicalType = schema.root()->logicalType(); + BOOST_CHECK(logicalType.type() == LogicalType::LOCAL_TIMESTAMP_MILLIS); + GenericDatum datum(schema); + BOOST_CHECK(datum.logicalType().type() == LogicalType::LOCAL_TIMESTAMP_MILLIS); + } + { + BOOST_TEST_CHECKPOINT(localTimestampMicrosType); + ValidSchema schema = compileJsonSchemaFromString(localTimestampMicrosType); + BOOST_CHECK(schema.root()->type() == AVRO_LONG); + LogicalType logicalType = schema.root()->logicalType(); + BOOST_CHECK(logicalType.type() == LogicalType::LOCAL_TIMESTAMP_MICROS); + GenericDatum datum(schema); + BOOST_CHECK(datum.logicalType().type() == LogicalType::LOCAL_TIMESTAMP_MICROS); + } { BOOST_TEST_CHECKPOINT(durationType); ValidSchema schema = compileJsonSchemaFromString(durationType);