You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by dl...@apache.org on 2021/09/28 15:42:10 UTC

[asterixdb] branch master updated: [NO ISSUE][FUN] Date/time printing/parsing enhancements

This is an automated email from the ASF dual-hosted git repository.

dlych pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 07c04d7  [NO ISSUE][FUN] Date/time printing/parsing enhancements
07c04d7 is described below

commit 07c04d7aa5fecd58a5c28177582345ca8e0213f4
Author: Dmitry Lychagin <dm...@couchbase.com>
AuthorDate: Mon Sep 27 12:38:20 2021 -0700

    [NO ISSUE][FUN] Date/time printing/parsing enhancements
    
    - user model changes: no
    - storage format changes: no
    - interface changes: no
    
    Details:
    - Enhance format characters supported by date/time printing/parsing
    - 'S' as an alternative to 'n' (milliseconds)
    - Replace 'W' (week day name) with 'EEE' (short name)
      and 'EEEE' (full name)
    - Allow 'MMMM' when parsing month (full month name)
    - Improve validation of parsed date/time values
    - Allow parsing standalone year and year-month
    - Add testcases and update documentation
    
    Change-Id: I453df2c22039a20a4972c818ab1bc4cd70daa461
    Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/13403
    Tested-by: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
    Reviewed-by: Ian Maxon <im...@uci.edu>
---
 .../queries_sqlpp/temporal/TemporalQueries.xml     |  14 +-
 .../temporal/parse_01/parse_01.3.query.sqlpp       |   2 +-
 .../temporal/parse_03/parse_03.1.query.sqlpp       |  31 +++++
 .../temporal/parse_03/parse_03.2.query.sqlpp       |  33 +++++
 .../temporal/parse_03/parse_03.3.query.sqlpp       |  33 +++++
 .../temporal/parse_03/parse_03.4.query.sqlpp       |  39 ++++++
 .../temporal/parse_03/parse_03.5.query.sqlpp       |  27 ++++
 .../temporal/print_01/print_01.4.query.sqlpp       |  32 +++++
 .../temporal/print_01/print_01.5.query.sqlpp       |  35 +++++
 .../results/temporal/parse_03/parse_03.1.adm       |   9 ++
 .../results/temporal/parse_03/parse_03.2.adm       |   7 +
 .../results/temporal/parse_03/parse_03.3.adm       |   7 +
 .../results/temporal/parse_03/parse_03.4.adm       |  12 ++
 .../results/temporal/parse_03/parse_03.5.adm       |   1 +
 .../results/temporal/print_01/print_01.4.adm       |   7 +
 .../results/temporal/print_01/print_01.5.adm       |   7 +
 .../temporal/parse_01/parse_01.3.ast               |   6 +-
 .../src/main/markdown/builtins/7_temporal.md       |  16 ++-
 .../om/base/temporal/DateTimeFormatUtils.java      | 146 ++++++++++++++++-----
 19 files changed, 420 insertions(+), 44 deletions(-)

diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/TemporalQueries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/TemporalQueries.xml
index 8b48ca6..4f77d69 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/TemporalQueries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/TemporalQueries.xml
@@ -63,13 +63,23 @@
       </compilation-unit>
     </test-case>
     <test-case FilePath="temporal">
+      <compilation-unit name="parse_01">
+        <output-dir compare="Text">parse_01</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="temporal">
       <compilation-unit name="parse_02">
         <output-dir compare="Text">parse_02</output-dir>
       </compilation-unit>
     </test-case>
     <test-case FilePath="temporal">
-      <compilation-unit name="parse_01">
-        <output-dir compare="Text">parse_01</output-dir>
+      <compilation-unit name="parse_03">
+        <output-dir compare="Text">parse_03</output-dir>
+      </compilation-unit>
+    </test-case>
+    <test-case FilePath="temporal">
+      <compilation-unit name="print_01">
+        <output-dir compare="Text">print_01</output-dir>
       </compilation-unit>
     </test-case>
     <test-case FilePath="temporal">
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_01/parse_01.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_01/parse_01.3.query.sqlpp
index 5a16610..0ee2fd1 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_01/parse_01.3.query.sqlpp
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_01/parse_01.3.query.sqlpp
@@ -24,4 +24,4 @@
 use test;
 
 
-select element {'date1':test.`parse-date`('2013-8-23','YY-M-D'),'date2':test.`parse-date`('Aug 12 -12','MMM D Y'),'date3':test.`parse-date`('-1234-01-01','YYYY-MM-DD'),'date4':test.`parse-date`('09/11/-1980','D/M/Y'),'date5':test.`parse-date`('09/11/-1990','YY-M-D|MMM D Y|D/M/Y'),'date6':test.`parse-date`('Mon Aug 19 2013','W MMM D Y'),'data7':test.`parse-date`('SKIPMEPLEASE Mon Aug SKIPME1ALSO 19 2013','O W MMM O D Y'),'time1':test.`parse-time`('8:23:49','h:m:s'),'time2':test.`parse-tim [...]
+select element {'date1':test.`parse-date`('2013-8-23','YY-M-D'),'date2':test.`parse-date`('Aug 12 -12','MMM D Y'),'date3':test.`parse-date`('-1234-01-01','YYYY-MM-DD'),'date4':test.`parse-date`('09/11/-1980','D/M/Y'),'date5':test.`parse-date`('09/11/-1990','YY-M-D|MMM D Y|D/M/Y'),'date6':test.`parse-date`('Mon Aug 19 2013','EEE MMM D Y'),'data7':test.`parse-date`('SKIPMEPLEASE Mon Aug SKIPME1ALSO 19 2013','O EEE MMM O D Y'),'time1':test.`parse-time`('8:23:49','h:m:s'),'time2':test.`parse [...]
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.1.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.1.query.sqlpp
new file mode 100644
index 0000000..125dfad
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.1.query.sqlpp
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Parse milliseconds using alternative format character (S)
+ */
+
+select
+  dt, string(parse_datetime(dt, "YYYY-MM-DDThh:mm:ss.SSS")) dt2,
+  t, string(parse_time(t, "hh:mm:ss.SSS")) t2
+from [0, 1, 9, 10, 99, 100, 999, 1999, 10999] r
+let
+  dt = string(datetime_from_unix_time_in_ms(r)),
+  t = string(time_from_unix_time_in_ms(r))
+order by r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.2.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.2.query.sqlpp
new file mode 100644
index 0000000..d982426
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.2.query.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Parse (and ignore) weekday
+ */
+
+with weekdays as ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
+
+select s3, d3, s4, d4
+from range(0, 6) r
+let s = "2021-07-2" || string(r),
+    s3 = s || " " || substr(weekdays[r], 0, 3),
+    s4 = s || " " || weekdays[r],
+    d3 = parse_date(s3,"YYYY-MM-DD EEE"),
+    d4 = parse_date(s4,"YYYY-MM-DD EEEE")
+order by r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.3.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.3.query.sqlpp
new file mode 100644
index 0000000..e3c6a47
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.3.query.sqlpp
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Parse (and ignore) weekday
+ */
+
+with weekdays as ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
+
+select s3, d3, s4, d4
+from range(0, 6) r
+let s = "2021-07-2" || string(r),
+    s3 = substr(weekdays[r], 0, 3) || " " || s,
+    s4 = weekdays[r] || " " || s,
+    d3 = parse_date(s3,"EEE YYYY-MM-DD"),
+    d4 = parse_date(s4,"EEEE YYYY-MM-DD")
+order by r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.4.query.sqlpp
new file mode 100644
index 0000000..35db859
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.4.query.sqlpp
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Parse month name
+ */
+
+ with months as [
+  "January", "February", "March", "April", "May", "June",
+  "July", "August", "September", "October", "November", "December"
+]
+select
+  s3m, parse_date(s3m, "YYYY-MMM") d3m,
+  s3d, parse_date(s3d, "YYYY-MMM-DD") d3d,
+  s4m, parse_date(s4m, "YYYY-MMMM") d4m,
+  s4d, parse_date(s4d, "YYYY-MMMM-DD") d4d
+from range(0, 11) r
+let
+  s3m = "2020-" || substr(months[r], 0, 3),
+  s3d = "2020-" || substr(months[r], 0, 3) || "-02",
+  s4m = "2020-" || months[r],
+  s4d = "2020-" || months[r] || "-02"
+order by r;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.5.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.5.query.sqlpp
new file mode 100644
index 0000000..3dc2b10
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/parse_03/parse_03.5.query.sqlpp
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Parse standalone year
+ */
+
+ {
+  "t1": parse_date("2020", "YYYY"),
+  "t2": parse_datetime("2020", "YYYY")
+ }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/print_01/print_01.4.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/print_01/print_01.4.query.sqlpp
new file mode 100644
index 0000000..6893a80
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/print_01/print_01.4.query.sqlpp
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Print day of week
+ */
+
+select r,
+  print_date(d, "EEE") d3, print_date(d, "EEEE") d4,
+  print_datetime(dt, "EEE") dt3, print_datetime(dt, "EEEE") dt4
+from range(0, 6) r
+let
+  d = date_from_unix_time_in_days(unix_time_from_date_in_days(date("2021-09-19")) + r),
+  dt = datetime_from_date_time(d, time("01:01:01"))
+order by r;
+
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/print_01/print_01.5.query.sqlpp b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/print_01/print_01.5.query.sqlpp
new file mode 100644
index 0000000..8aeb8bd
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/temporal/print_01/print_01.5.query.sqlpp
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+ * Print milliseconds using alternative format character (S)
+ */
+
+select r ms,
+  print_datetime(dt, "s.S") dt1,
+  print_datetime(dt, "s.SS") dt2,
+  print_datetime(dt, "s.SSS") dt3,
+  print_time(t, "s.S" ) t1,
+  print_time(t, "s.SS" ) t2,
+  print_time(t, "s.SSS" ) t3
+from [0, 1, 9, 10, 99, 100, 999] r
+let
+  dt = datetime_from_unix_time_in_ms(r),
+  t = time_from_unix_time_in_ms(r)
+order by r;
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.1.adm
new file mode 100644
index 0000000..cbc02e6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.1.adm
@@ -0,0 +1,9 @@
+{ "dt": "1970-01-01T00:00:00.000", "dt2": "1970-01-01T00:00:00.000", "t": "00:00:00.000", "t2": "00:00:00.000" }
+{ "dt": "1970-01-01T00:00:00.001", "dt2": "1970-01-01T00:00:00.001", "t": "00:00:00.001", "t2": "00:00:00.001" }
+{ "dt": "1970-01-01T00:00:00.009", "dt2": "1970-01-01T00:00:00.009", "t": "00:00:00.009", "t2": "00:00:00.009" }
+{ "dt": "1970-01-01T00:00:00.010", "dt2": "1970-01-01T00:00:00.010", "t": "00:00:00.010", "t2": "00:00:00.010" }
+{ "dt": "1970-01-01T00:00:00.099", "dt2": "1970-01-01T00:00:00.099", "t": "00:00:00.099", "t2": "00:00:00.099" }
+{ "dt": "1970-01-01T00:00:00.100", "dt2": "1970-01-01T00:00:00.100", "t": "00:00:00.100", "t2": "00:00:00.100" }
+{ "dt": "1970-01-01T00:00:00.999", "dt2": "1970-01-01T00:00:00.999", "t": "00:00:00.999", "t2": "00:00:00.999" }
+{ "dt": "1970-01-01T00:00:01.999", "dt2": "1970-01-01T00:00:01.999", "t": "00:00:01.999", "t2": "00:00:01.999" }
+{ "dt": "1970-01-01T00:00:10.999", "dt2": "1970-01-01T00:00:10.999", "t": "00:00:10.999", "t2": "00:00:10.999" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.2.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.2.adm
new file mode 100644
index 0000000..4dd895b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.2.adm
@@ -0,0 +1,7 @@
+{ "s3": "2021-07-20 Sun", "d3": date("2021-07-20"), "s4": "2021-07-20 Sunday", "d4": date("2021-07-20") }
+{ "s3": "2021-07-21 Mon", "d3": date("2021-07-21"), "s4": "2021-07-21 Monday", "d4": date("2021-07-21") }
+{ "s3": "2021-07-22 Tue", "d3": date("2021-07-22"), "s4": "2021-07-22 Tuesday", "d4": date("2021-07-22") }
+{ "s3": "2021-07-23 Wed", "d3": date("2021-07-23"), "s4": "2021-07-23 Wednesday", "d4": date("2021-07-23") }
+{ "s3": "2021-07-24 Thu", "d3": date("2021-07-24"), "s4": "2021-07-24 Thursday", "d4": date("2021-07-24") }
+{ "s3": "2021-07-25 Fri", "d3": date("2021-07-25"), "s4": "2021-07-25 Friday", "d4": date("2021-07-25") }
+{ "s3": "2021-07-26 Sat", "d3": date("2021-07-26"), "s4": "2021-07-26 Saturday", "d4": date("2021-07-26") }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.3.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.3.adm
new file mode 100644
index 0000000..8d26ff5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.3.adm
@@ -0,0 +1,7 @@
+{ "s3": "Sun 2021-07-20", "d3": date("2021-07-20"), "s4": "Sunday 2021-07-20", "d4": date("2021-07-20") }
+{ "s3": "Mon 2021-07-21", "d3": date("2021-07-21"), "s4": "Monday 2021-07-21", "d4": date("2021-07-21") }
+{ "s3": "Tue 2021-07-22", "d3": date("2021-07-22"), "s4": "Tuesday 2021-07-22", "d4": date("2021-07-22") }
+{ "s3": "Wed 2021-07-23", "d3": date("2021-07-23"), "s4": "Wednesday 2021-07-23", "d4": date("2021-07-23") }
+{ "s3": "Thu 2021-07-24", "d3": date("2021-07-24"), "s4": "Thursday 2021-07-24", "d4": date("2021-07-24") }
+{ "s3": "Fri 2021-07-25", "d3": date("2021-07-25"), "s4": "Friday 2021-07-25", "d4": date("2021-07-25") }
+{ "s3": "Sat 2021-07-26", "d3": date("2021-07-26"), "s4": "Saturday 2021-07-26", "d4": date("2021-07-26") }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.4.adm
new file mode 100644
index 0000000..35d1aed
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.4.adm
@@ -0,0 +1,12 @@
+{ "s3m": "2020-Jan", "d3m": date("2020-01-01"), "s3d": "2020-Jan-02", "d3d": date("2020-01-02"), "s4m": "2020-January", "d4m": date("2020-01-01"), "s4d": "2020-January-02", "d4d": date("2020-01-02") }
+{ "s3m": "2020-Feb", "d3m": date("2020-02-01"), "s3d": "2020-Feb-02", "d3d": date("2020-02-02"), "s4m": "2020-February", "d4m": date("2020-02-01"), "s4d": "2020-February-02", "d4d": date("2020-02-02") }
+{ "s3m": "2020-Mar", "d3m": date("2020-03-01"), "s3d": "2020-Mar-02", "d3d": date("2020-03-02"), "s4m": "2020-March", "d4m": date("2020-03-01"), "s4d": "2020-March-02", "d4d": date("2020-03-02") }
+{ "s3m": "2020-Apr", "d3m": date("2020-04-01"), "s3d": "2020-Apr-02", "d3d": date("2020-04-02"), "s4m": "2020-April", "d4m": date("2020-04-01"), "s4d": "2020-April-02", "d4d": date("2020-04-02") }
+{ "s3m": "2020-May", "d3m": date("2020-05-01"), "s3d": "2020-May-02", "d3d": date("2020-05-02"), "s4m": "2020-May", "d4m": date("2020-05-01"), "s4d": "2020-May-02", "d4d": date("2020-05-02") }
+{ "s3m": "2020-Jun", "d3m": date("2020-06-01"), "s3d": "2020-Jun-02", "d3d": date("2020-06-02"), "s4m": "2020-June", "d4m": date("2020-06-01"), "s4d": "2020-June-02", "d4d": date("2020-06-02") }
+{ "s3m": "2020-Jul", "d3m": date("2020-07-01"), "s3d": "2020-Jul-02", "d3d": date("2020-07-02"), "s4m": "2020-July", "d4m": date("2020-07-01"), "s4d": "2020-July-02", "d4d": date("2020-07-02") }
+{ "s3m": "2020-Aug", "d3m": date("2020-08-01"), "s3d": "2020-Aug-02", "d3d": date("2020-08-02"), "s4m": "2020-August", "d4m": date("2020-08-01"), "s4d": "2020-August-02", "d4d": date("2020-08-02") }
+{ "s3m": "2020-Sep", "d3m": date("2020-09-01"), "s3d": "2020-Sep-02", "d3d": date("2020-09-02"), "s4m": "2020-September", "d4m": date("2020-09-01"), "s4d": "2020-September-02", "d4d": date("2020-09-02") }
+{ "s3m": "2020-Oct", "d3m": date("2020-10-01"), "s3d": "2020-Oct-02", "d3d": date("2020-10-02"), "s4m": "2020-October", "d4m": date("2020-10-01"), "s4d": "2020-October-02", "d4d": date("2020-10-02") }
+{ "s3m": "2020-Nov", "d3m": date("2020-11-01"), "s3d": "2020-Nov-02", "d3d": date("2020-11-02"), "s4m": "2020-November", "d4m": date("2020-11-01"), "s4d": "2020-November-02", "d4d": date("2020-11-02") }
+{ "s3m": "2020-Dec", "d3m": date("2020-12-01"), "s3d": "2020-Dec-02", "d3d": date("2020-12-02"), "s4m": "2020-December", "d4m": date("2020-12-01"), "s4d": "2020-December-02", "d4d": date("2020-12-02") }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.5.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.5.adm
new file mode 100644
index 0000000..d78e574
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/parse_03/parse_03.5.adm
@@ -0,0 +1 @@
+{ "t1": date("2020-01-01"), "t2": datetime("2020-01-01T00:00:00.000") }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/print_01/print_01.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/print_01/print_01.4.adm
new file mode 100644
index 0000000..51db528
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/print_01/print_01.4.adm
@@ -0,0 +1,7 @@
+{ "r": 0, "d3": "Sun", "d4": "Sunday", "dt3": "Sun", "dt4": "Sunday" }
+{ "r": 1, "d3": "Mon", "d4": "Monday", "dt3": "Mon", "dt4": "Monday" }
+{ "r": 2, "d3": "Tue", "d4": "Tuesday", "dt3": "Tue", "dt4": "Tuesday" }
+{ "r": 3, "d3": "Wed", "d4": "Wednesday", "dt3": "Wed", "dt4": "Wednesday" }
+{ "r": 4, "d3": "Thu", "d4": "Thursday", "dt3": "Thu", "dt4": "Thursday" }
+{ "r": 5, "d3": "Fri", "d4": "Friday", "dt3": "Fri", "dt4": "Friday" }
+{ "r": 6, "d3": "Sat", "d4": "Saturday", "dt3": "Sat", "dt4": "Saturday" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/print_01/print_01.5.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/print_01/print_01.5.adm
new file mode 100644
index 0000000..54f1685
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/temporal/print_01/print_01.5.adm
@@ -0,0 +1,7 @@
+{ "ms": 0, "dt1": "0.000", "dt2": "0.000", "dt3": "0.000", "t1": "0.000", "t2": "0.000", "t3": "0.000" }
+{ "ms": 1, "dt1": "0.001", "dt2": "0.001", "dt3": "0.001", "t1": "0.001", "t2": "0.001", "t3": "0.001" }
+{ "ms": 9, "dt1": "0.009", "dt2": "0.009", "dt3": "0.009", "t1": "0.009", "t2": "0.009", "t3": "0.009" }
+{ "ms": 10, "dt1": "0.01", "dt2": "0.01", "dt3": "0.010", "t1": "0.01", "t2": "0.01", "t3": "0.010" }
+{ "ms": 99, "dt1": "0.099", "dt2": "0.099", "dt3": "0.099", "t1": "0.099", "t2": "0.099", "t3": "0.099" }
+{ "ms": 100, "dt1": "0.1", "dt2": "0.10", "dt3": "0.100", "t1": "0.1", "t2": "0.10", "t3": "0.100" }
+{ "ms": 999, "dt1": "0.999", "dt2": "0.999", "dt3": "0.999", "t1": "0.999", "t2": "0.999", "t3": "0.999" }
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/parse_01/parse_01.3.ast b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/parse_01/parse_01.3.ast
index 08e0b89..39490af 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/parse_01/parse_01.3.ast
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_parser_sqlpp/temporal/parse_01/parse_01.3.ast
@@ -47,7 +47,7 @@ RecordConstructor [
     :
     FunctionCall asterix.parse-date@2[
       LiteralExpr [STRING] [Mon Aug 19 2013]
-      LiteralExpr [STRING] [W MMM D Y]
+      LiteralExpr [STRING] [EEE MMM D Y]
     ]
   )
   (
@@ -55,7 +55,7 @@ RecordConstructor [
     :
     FunctionCall asterix.parse-date@2[
       LiteralExpr [STRING] [SKIPMEPLEASE Mon Aug SKIPME1ALSO 19 2013]
-      LiteralExpr [STRING] [O W MMM O D Y]
+      LiteralExpr [STRING] [O EEE MMM O D Y]
     ]
   )
   (
@@ -143,7 +143,7 @@ RecordConstructor [
     :
     FunctionCall asterix.parse-datetime@2[
       LiteralExpr [STRING] [1970-01-01 Thu 23:59:23.392-04:00]
-      LiteralExpr [STRING] [MMM DD YYYY h:m:s a|MM/DD/YYY hh:mm:ss.nnn a z|YYYY-MM-DD W hh:mm:ss.nnnz]
+      LiteralExpr [STRING] [MMM DD YYYY h:m:s a|MM/DD/YYY hh:mm:ss.nnn a z|YYYY-MM-DD EEE hh:mm:ss.nnnz]
     ]
   )
   (
diff --git a/asterixdb/asterix-doc/src/main/markdown/builtins/7_temporal.md b/asterixdb/asterix-doc/src/main/markdown/builtins/7_temporal.md
index dcb252b..5c11b46 100644
--- a/asterixdb/asterix-doc/src/main/markdown/builtins/7_temporal.md
+++ b/asterixdb/asterix-doc/src/main/markdown/builtins/7_temporal.md
@@ -644,13 +644,14 @@ parse_date/parse_time/parse_datetime(date,formatting_expression)
        * `h` hours
        * `m` minutes
        * `s` seconds
-       * `n` milliseconds
+       * `n` (or `S`) milliseconds
        * `a` am/pm
-       * `z` timezone
+       * `z` timezone (parsed and ignored)
        * `Y` year
        * `M` month
        * `D` day
-       * `W` weekday
+       * `EEE` weekday (abbreviated name, parsed and ignored)
+       * `EEEE` weekday (full name, parsed and ignored)
        * `_`, `'`, `/`, `.`, `,`, `T` seperators for both time and date
 * Return Value:
     * a `date/time/date_time` value corresponding to `date`,
@@ -681,13 +682,16 @@ parse_date/parse_time/parse_datetime(date,formatting_expression)
        * `h` hours
        * `m` minutes
        * `s` seconds
-       * `n` milliseconds
+       * `n` (or `S`) milliseconds
        * `a` am/pm
-       * `z` timezone
        * `Y` year
        * `M` month
+       * `MMM` month (abbreviated name)
+       * `MMMM` month (full name)
        * `D` day
-       * `W` weekday
+       * `DDD` day of year 
+       * `EEE` weekday (abbreviated name)
+       * `EEEE` weekday (full name)
        * `_`, `'`, `/`, `.`, `,`, `T` seperators for both time and date
 * Return Value:
     * a `string` value corresponding to `date`,
diff --git a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DateTimeFormatUtils.java b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DateTimeFormatUtils.java
index 11e6395..73ba3d8 100644
--- a/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DateTimeFormatUtils.java
+++ b/asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/DateTimeFormatUtils.java
@@ -65,6 +65,7 @@ public class DateTimeFormatUtils {
     private static final char MINUTE_CHAR = 'm';
     private static final char SECOND_CHAR = 's';
     private static final char MILLISECOND_CHAR = 'n';
+    private static final char MILLISECOND_CHAR_ALT = 'S';
     private static final char AMPM_CHAR = 'a';
     private static final char TIMEZONE_CHAR = 'z';
 
@@ -96,15 +97,15 @@ public class DateTimeFormatUtils {
     private static final char QUARTER_CHAR = 'Q';
     private static final char MONTH_CHAR = 'M';
     private static final char DAY_CHAR = 'D';
-    private static final char WEEKDAY_CHAR = 'W';
+    private static final char WEEKDAY_CHAR = 'E';
 
     private static final int MAX_YEAR_CHARS = 4;
     private static final int MAX_QUARTER_CHARS = 1;
-    private static final int MAX_MONTH_CHARS_PARSE = 3;
-    private static final int MAX_MONTH_CHARS_PRINT = 4;
+    private static final int MAX_MONTH_CHARS = 4;
     private static final int MAX_DAY_CHARS_PARSE = 2;
     private static final int MAX_DAY_CHARS_PRINT = 3; // + DDD = Day of Year
-    private static final int MAX_WEEKDAY_CHAR = 1;
+    private static final int MIN_WEEKDAY_CHAR = 3;
+    private static final int MAX_WEEKDAY_CHAR = 4;
 
     private static final byte[][] MONTH_NAMES = new byte[][] { "jan".getBytes(ENCODING), "feb".getBytes(ENCODING),
             "mar".getBytes(ENCODING), "apr".getBytes(ENCODING), "may".getBytes(ENCODING), "jun".getBytes(ENCODING),
@@ -191,7 +192,7 @@ public class DateTimeFormatUtils {
     }
 
     private int parseFormatField(byte[] format, int formatStart, int formatLength, int formatPointer, char formatChar,
-            int maxAllowedFormatCharCopied) {
+            int maxAllowedFormatCharCopied) throws AsterixTemporalTypeParseException {
 
         int formatCharCopies = 0;
 
@@ -202,7 +203,7 @@ public class DateTimeFormatUtils {
             formatCharCopies++;
         }
         if (formatCharCopies > maxAllowedFormatCharCopied) {
-            throw new IllegalStateException(
+            throw new AsterixTemporalTypeParseException(
                     "The format string for " + formatChar + " is too long: expected no more than "
                             + maxAllowedFormatCharCopied + " but got " + formatCharCopies);
         }
@@ -239,18 +240,21 @@ public class DateTimeFormatUtils {
         return beginWith;
     }
 
-    private int monthIDSearch(byte[] barray, int start, int length) {
-        for (int i = 0; i < MONTH_NAMES.length; i++) {
-            if (byteArrayEqualToString(barray, start, length, MONTH_NAMES[i])) {
+    private int monthIDSearch(byte[] barray, int start, int length, boolean useShortNames) {
+        byte[][] monthNames = useShortNames ? MONTH_NAMES : MONTH_FULL_NAMES;
+        for (int i = 0; i < monthNames.length; i++) {
+            if (byteArrayEqualToString(barray, start, length, monthNames[i])) {
                 return i;
             }
         }
         return -1;
     }
 
-    public static int weekdayIDSearchLax(byte[] barray, int start, int length) {
-        for (int i = 0; i < WEEKDAY_FULL_NAMES.length; i++) {
-            if (byteArrayBeingWithString(barray, start, length, WEEKDAY_FULL_NAMES[i])) {
+    @Deprecated
+    public static int weekdayIDSearchLax(byte[] barray, int start, int length, boolean useShortNames) {
+        byte[][] weekdayNames = useShortNames ? WEEKDAY_NAMES : WEEKDAY_FULL_NAMES;
+        for (int i = 0; i < weekdayNames.length; i++) {
+            if (byteArrayBeingWithString(barray, start, length, weekdayNames[i])) {
                 return i;
             }
         }
@@ -340,7 +344,7 @@ public class DateTimeFormatUtils {
                 case MONTH_CHAR:
                     processState = DateTimeProcessState.MONTH;
                     pointerMove = parseFormatField(format, formatStart, formatLength, formatPointer, MONTH_CHAR,
-                            MAX_MONTH_CHARS_PARSE);
+                            MAX_MONTH_CHARS);
                     formatPointer += pointerMove;
                     formatCharCopies += pointerMove;
                     break;
@@ -355,6 +359,11 @@ public class DateTimeFormatUtils {
                     processState = DateTimeProcessState.WEEKDAY;
                     pointerMove = parseFormatField(format, formatStart, formatLength, formatPointer, WEEKDAY_CHAR,
                             MAX_WEEKDAY_CHAR);
+                    if (pointerMove < MIN_WEEKDAY_CHAR) {
+                        throw new AsterixTemporalTypeParseException(
+                                String.format("Expected at least %d '%s' characters but got %d", MIN_WEEKDAY_CHAR,
+                                        WEEKDAY_CHAR, pointerMove));
+                    }
                     formatPointer += pointerMove;
                     formatCharCopies += pointerMove;
                     break;
@@ -386,7 +395,13 @@ public class DateTimeFormatUtils {
                     formatPointer += pointerMove;
                     formatCharCopies += pointerMove;
                     break;
-
+                case MILLISECOND_CHAR_ALT:
+                    processState = DateTimeProcessState.MILLISECOND;
+                    pointerMove = parseFormatField(format, formatStart, formatLength, formatPointer,
+                            MILLISECOND_CHAR_ALT, MAX_MILLISECOND_CHARS);
+                    formatPointer += pointerMove;
+                    formatCharCopies += pointerMove;
+                    break;
                 case AMPM_CHAR:
                     processState = DateTimeProcessState.AMPM;
                     pointerMove = parseFormatField(format, formatStart, formatLength, formatPointer, AMPM_CHAR,
@@ -430,7 +445,7 @@ public class DateTimeFormatUtils {
 
                 default:
                     throw new AsterixTemporalTypeParseException("Unexpected date format string at "
-                            + (formatStart + formatPointer) + ": " + format[formatStart + formatPointer]);
+                            + (formatStart + formatPointer) + ": " + (char) format[formatStart + formatPointer]);
             }
 
             // check whether the process state is valid for the parse mode
@@ -468,7 +483,6 @@ public class DateTimeFormatUtils {
                 case DAY:
                     int maxAllowedFormatCharCopies = (processState == DateTimeProcessState.YEAR) ? 4 : 2;
                     int parsedValue = 0;
-
                     int processedFieldsCount = 0;
                     for (int i = 0; i < formatCharCopies; i++) {
                         if (data[dataStart + dataStringPointer] < '0' || data[dataStart + dataStringPointer] > '9') {
@@ -496,6 +510,13 @@ public class DateTimeFormatUtils {
                         if (negativeYear) {
                             year *= -1;
                         }
+                        // Allow month and day to be missing if we parsed year
+                        if (month == 0) {
+                            month = GregorianCalendarSystem.FIELD_MINS[GregorianCalendarSystem.Fields.MONTH.ordinal()];
+                        }
+                        if (day == 0) {
+                            day = GregorianCalendarSystem.FIELD_MINS[GregorianCalendarSystem.Fields.DAY.ordinal()];
+                        }
                     } else {
                         if (parsedValue == 0) {
                             if (raiseParseDataError) {
@@ -509,12 +530,22 @@ public class DateTimeFormatUtils {
                     }
                     break;
                 case MONTH:
-                    if (formatCharCopies == 3) {
+                    if (formatCharCopies >= 3) {
                         // the month is in the text format
-                        int monthNameMatch = monthIDSearch(data, dataStart + dataStringPointer, 3);
+                        int processedMonthFieldsCount = 0;
+                        while (((dataStringPointer + processedMonthFieldsCount < dataLength)) && ((data[dataStart
+                                + dataStringPointer + processedMonthFieldsCount] >= 'a'
+                                && data[dataStart + dataStringPointer + processedMonthFieldsCount] <= 'z')
+                                || (data[dataStart + dataStringPointer + processedMonthFieldsCount] >= 'A'
+                                        && data[dataStart + dataStringPointer + processedMonthFieldsCount] <= 'Z'))) {
+                            processedMonthFieldsCount++;
+                        }
+                        boolean useShortNames = formatCharCopies == 3;
+                        int monthNameMatch = monthIDSearch(data, dataStart + dataStringPointer,
+                                processedMonthFieldsCount, useShortNames);
                         if (monthNameMatch >= 0) {
                             month = monthNameMatch + 1;
-                            dataStringPointer += 3;
+                            dataStringPointer += processedMonthFieldsCount;
                         } else {
                             if (raiseParseDataError) {
                                 throw new AsterixTemporalTypeParseException(
@@ -526,6 +557,8 @@ public class DateTimeFormatUtils {
                             }
                         }
                     } else {
+                        // the month is in the number format
+                        parsedValue = 0;
                         int processedMonthFieldsCount = 0;
                         for (int i = 0; i < formatCharCopies; i++) {
                             if (data[dataStart + dataStringPointer] < '0'
@@ -538,7 +571,7 @@ public class DateTimeFormatUtils {
                                     return false;
                                 }
                             }
-                            month = month * 10 + (data[dataStart + dataStringPointer] - '0');
+                            parsedValue = parsedValue * 10 + (data[dataStart + dataStringPointer] - '0');
                             dataStringPointer++;
                             if (processedMonthFieldsCount++ > 2) {
                                 if (raiseParseDataError) {
@@ -550,15 +583,15 @@ public class DateTimeFormatUtils {
                                 }
                             }
                         }
-                        // if there are more than 2 digits for the day string
+                        // if there are more than 2 digits for the month string
                         while (processedMonthFieldsCount < 2 && dataStringPointer < dataLength
                                 && data[dataStart + dataStringPointer] >= '0'
                                 && data[dataStart + dataStringPointer] <= '9') {
-                            month = month * 10 + (data[dataStart + dataStringPointer] - '0');
+                            parsedValue = parsedValue * 10 + (data[dataStart + dataStringPointer] - '0');
                             dataStringPointer++;
                             processedMonthFieldsCount++;
                         }
-                        if (month == 0) {
+                        if (parsedValue == 0) {
                             if (raiseParseDataError) {
                                 throw new AsterixTemporalTypeParseException(
                                         "Incorrect month value at " + (dataStart + dataStringPointer));
@@ -566,18 +599,27 @@ public class DateTimeFormatUtils {
                                 return false;
                             }
                         }
+                        month = parsedValue;
+                    }
+                    // Allow day to be missing if we parsed month
+                    if (day == 0) {
+                        day = GregorianCalendarSystem.FIELD_MINS[GregorianCalendarSystem.Fields.DAY.ordinal()];
                     }
                     break;
                 case WEEKDAY:
                     int processedWeekdayFieldsCount = 0;
-                    while ((data[dataStart + dataStringPointer + processedWeekdayFieldsCount] >= 'a'
+                    while ((dataStringPointer + processedWeekdayFieldsCount < dataLength) && ((data[dataStart
+                            + dataStringPointer + processedWeekdayFieldsCount] >= 'a'
                             && data[dataStart + dataStringPointer + processedWeekdayFieldsCount] <= 'z')
                             || (data[dataStart + dataStringPointer + processedWeekdayFieldsCount] >= 'A'
-                                    && data[dataStart + dataStringPointer + processedWeekdayFieldsCount] <= 'Z')) {
+                                    && data[dataStart + dataStringPointer + processedWeekdayFieldsCount] <= 'Z'))) {
                         processedWeekdayFieldsCount++;
                     }
                     // match the weekday name
-                    if (weekdayIDSearchLax(data, dataStart + dataStringPointer, processedWeekdayFieldsCount) < 0) {
+                    boolean useShortNames = formatCharCopies == 3;
+                    int weekdayNameMatch = weekdayIDSearch(data, dataStart + dataStringPointer,
+                            processedWeekdayFieldsCount, useShortNames);
+                    if (weekdayNameMatch < 0) {
                         if (raiseParseDataError) {
                             throw new AsterixTemporalTypeParseException("Unexpected string for day-of-week: "
                                     + new String(data, dataStart + dataStringPointer,
@@ -842,10 +884,38 @@ public class DateTimeFormatUtils {
             }
         }
 
-        long chronon = parseMode == DateTimeParseMode.TIME_ONLY ? CAL.getChronon(hour, min, sec, ms)
-                : CAL.getChronon(year, month, day, hour, min, sec, ms);
+        long chronon;
+        if (parseMode == DateTimeParseMode.TIME_ONLY) {
+            int minYear = GregorianCalendarSystem.FIELD_MINS[GregorianCalendarSystem.Fields.YEAR.ordinal()];
+            int minMonth = GregorianCalendarSystem.FIELD_MINS[GregorianCalendarSystem.Fields.MONTH.ordinal()];
+            int minDay = GregorianCalendarSystem.FIELD_MINS[GregorianCalendarSystem.Fields.DAY.ordinal()];
+            if (!CAL.validate(minYear, minMonth, minDay, hour, min, sec, ms)) {
+                if (raiseParseDataError) {
+                    throw new AsterixTemporalTypeParseException("Invalid time value");
+                } else {
+                    return false;
+                }
+            }
+            chronon = CAL.getChronon(hour, min, sec, ms);
+        } else {
+            if (!CAL.validate(year, month, day, hour, min, sec, ms)) {
+                if (raiseParseDataError) {
+                    throw new AsterixTemporalTypeParseException("Invalid date/time value");
+                } else {
+                    return false;
+                }
+            }
+            chronon = CAL.getChronon(year, month, day, hour, min, sec, ms);
+        }
 
         if (timezoneExists && adjustChrononByTimezone) {
+            if (!CAL.validateTimeZone(timezone)) {
+                if (raiseParseDataError) {
+                    throw new AsterixTemporalTypeParseException("Invalid time zone");
+                } else {
+                    return false;
+                }
+            }
             chronon += timezone;
         }
 
@@ -917,7 +987,7 @@ public class DateTimeFormatUtils {
                 case MONTH_CHAR:
                     processState = DateTimeProcessState.MONTH;
                     pointerMove = parseFormatField(format, formatStart, formatLength, formatPointer, MONTH_CHAR,
-                            MAX_MONTH_CHARS_PRINT);
+                            MAX_MONTH_CHARS);
                     formatPointer += pointerMove;
                     formatCharCopies += pointerMove;
                     break;
@@ -931,7 +1001,12 @@ public class DateTimeFormatUtils {
                 case WEEKDAY_CHAR:
                     processState = DateTimeProcessState.WEEKDAY;
                     pointerMove = parseFormatField(format, formatStart, formatLength, formatPointer, WEEKDAY_CHAR,
-                            WEEKDAY_CHAR);
+                            MAX_WEEKDAY_CHAR);
+                    if (pointerMove < MIN_WEEKDAY_CHAR) {
+                        throw new AsterixTemporalTypeParseException(
+                                String.format("Expected at least %d '%s' characters but got %d", MIN_WEEKDAY_CHAR,
+                                        WEEKDAY_CHAR, pointerMove));
+                    }
                     formatPointer += pointerMove;
                     formatCharCopies += pointerMove;
                     break;
@@ -963,7 +1038,13 @@ public class DateTimeFormatUtils {
                     formatPointer += pointerMove;
                     formatCharCopies += pointerMove;
                     break;
-
+                case MILLISECOND_CHAR_ALT:
+                    processState = DateTimeProcessState.MILLISECOND;
+                    pointerMove = parseFormatField(format, formatStart, formatLength, formatPointer,
+                            MILLISECOND_CHAR_ALT, MAX_MILLISECOND_CHARS);
+                    formatPointer += pointerMove;
+                    formatCharCopies += pointerMove;
+                    break;
                 case AMPM_CHAR:
                     processState = DateTimeProcessState.AMPM;
                     pointerMove = parseFormatField(format, formatStart, formatLength, formatPointer, AMPM_CHAR,
@@ -1056,7 +1137,8 @@ public class DateTimeFormatUtils {
                         appender.append(strVal);
                         break;
                     case WEEKDAY:
-                        byte[] weekday = WEEKDAY_FULL_NAMES[dayOfWeek];
+                        byte[][] weekdayNames = formatCharCopies == 3 ? WEEKDAY_NAMES : WEEKDAY_FULL_NAMES;
+                        byte[] weekday = weekdayNames[dayOfWeek];
                         for (int i = 0; i < weekday.length; i++) {
                             byte b = weekday[i];
                             appender.append((char) (i == 0 ? toUpper(b) : b));