mattyb149 commented on a change in pull request #4463:
URL: https://github.com/apache/nifi/pull/4463#discussion_r468208253



##########
File path: 
nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/test/java/org/apache/nifi/processors/cassandra/QueryCassandraTest.java
##########
@@ -368,6 +380,42 @@ public void testConvertToJSONStream() throws Exception {
         assertEquals(2, numberOfRows);
     }
 
+    @Test
+    public void testDefaultDateFormatInConvertToJSONStream() throws Exception {
+        ResultSet rs = CassandraQueryTestUtil.createMockDateResultSet();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        DateFormat df = new 
SimpleDateFormat(QueryCassandra.DATE_FORMAT_PATTERN.getDefaultValue());
+        df.setTimeZone(TimeZone.getTimeZone("UTC"));
+
+        long numberOfRows = 
QueryCassandra.convertToJsonStream(Optional.of(testRunner.getProcessContext()), 
rs, baos,
+            StandardCharsets.UTF_8, 0, null);
+        assertEquals(1, numberOfRows);
+
+        Map<String, List<Map<String, String>>> map = new 
ObjectMapper().readValue(baos.toByteArray(), HashMap.class);
+        String date = map.get("results").get(0).get("date");
+        assertEquals(df.format(CassandraQueryTestUtil.TEST_DATE), date);
+    }
+
+    @Test
+    public void testCustomDateFormatInConvertToJSONStream() throws Exception {
+        MockProcessContext context = (MockProcessContext) 
testRunner.getProcessContext();
+        ResultSet rs = CassandraQueryTestUtil.createMockDateResultSet();
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+        final String customDateFormat = "yyyy-MM-dd HH:mm:ss.SSSZ";

Review comment:
       I might be reading this incorrectly, but shouldn't we try a non-default 
value here, such as a timezone -1 hour from UTC?

##########
File path: 
nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/main/java/org/apache/nifi/processors/cassandra/QueryCassandra.java
##########
@@ -130,6 +132,23 @@
             .defaultValue(AVRO_FORMAT)
             .build();
 
+    public static final PropertyDescriptor DATE_FORMAT_PATTERN = new 
PropertyDescriptor.Builder()

Review comment:
       TL;DR I think this should be called "Timestamp Format Pattern for JSON 
output":
   
   I think (for now) we have to be pretty specific about the fields this 
property works upon. For example there is a separate bug (that should be 
written up as a Jira) where the CQL `DATE` type is not fully supported. For 
example, their `DATE` type returns a Cassandra-specific `LocalDate` class, 
which cannot currently be translated to an Avro schema, and in the current code 
(PR included) it drops through the JSON `instanceof Date` clause and is issued 
as `value.toString()`. So being a `java.util.Date` type lends itself to a 
Cassandra `TIMESTAMP` type, which is reflected in the unit tests. It's odd to 
me that they return a `java.util.Date` when (from [other 
sources](http://itdoc.hitachi.co.jp/manuals/3020/30203V0300e/BV030040.HTM), a 
vendor not the community) it appears they have a full-fledged 
`java.sql.Timestamp` object under the hood, yet we can only access a Date 
object so we can't get things like nanoseconds.
   
   We should revisit the `DATE` and `TIME` datatypes under a separate Jira but 
since this only seems to apply to the `TIMESTAMP` type, I'm thinking we should 
name it as such. I believe the JsonRecordSetWriter does something similar (i.e. 
has properties for date, time, timestamp formats)

##########
File path: 
nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/main/java/org/apache/nifi/processors/cassandra/QueryCassandra.java
##########
@@ -467,19 +494,30 @@ public static long convertToJsonStream(final ResultSet 
rs, final OutputStream ou
     }
 
     protected static String getJsonElement(Object value) {
+        return getJsonElement(Optional.empty(), value);
+    }
+
+    protected static String getJsonElement(final Optional<ProcessContext> 
context, Object value) {
         if (value instanceof Number) {
             return value.toString();
         } else if (value instanceof Date) {
-            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd 
HH:mm:ssZ");
-            dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
-            return "\"" + dateFormat.format((Date) value) + "\"";
+            return "\"" + getFormattedDate(context, (Date) value) + "\"";
         } else if (value instanceof String) {
             return "\"" + StringEscapeUtils.escapeJson((String) value) + "\"";
         } else {
             return "\"" + value.toString() + "\"";
         }
     }
 
+    private static String getFormattedDate(final Optional<ProcessContext> 
context, Date value) {
+        final String dateFormatPattern = context
+                .map(_context -> 
_context.getProperty(DATE_FORMAT_PATTERN).getValue())
+                .orElse(DATE_FORMAT_PATTERN.getDefaultValue());
+        SimpleDateFormat dateFormat = new SimpleDateFormat(dateFormatPattern);
+        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

Review comment:
       Can/do we need to get the timezone from the specified format? In any 
case let's make sure the doc is clear on what is output. Also should we migrate 
from SimpleDateFormat to the newer `java.time` classes? It can definitely be a 
pain but I wonder if it is more accommodating in the long run.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to