@@ -212,7 +212,8 @@ impl Parser {
212212 expr : Box :: new ( self . parse_subexpr ( Self :: UNARY_NOT_PREC ) ?) ,
213213 } ) ,
214214 "TIME" => Ok ( Expr :: Value ( Value :: Time ( self . parse_literal_string ( ) ?) ) ) ,
215- "TIMESTAMP" => Ok ( Expr :: Value ( self . parse_timestamp ( ) ?) ) ,
215+ "TIMESTAMP" => self . parse_timestamp ( ) ,
216+ "TIMESTAMPTZ" => self . parse_timestamptz ( ) ,
216217 // Here `w` is a word, check if it's a part of a multi-part
217218 // identifier, a function call, or a simple identifier:
218219 _ => match self . peek_token ( ) {
@@ -508,16 +509,46 @@ impl Parser {
508509 }
509510 }
510511
511- fn parse_timestamp ( & mut self ) -> Result < Value , ParserError > {
512+ fn parse_timestamp ( & mut self ) -> Result < Expr , ParserError > {
513+ if self . parse_keyword ( "WITH" ) {
514+ self . expect_keywords ( & [ "TIME" , "ZONE" ] ) ?;
515+ return Ok ( Expr :: Value ( self . parse_timestamp_inner ( true ) ?) ) ;
516+ } else if self . parse_keyword ( "WITHOUT" ) {
517+ self . expect_keywords ( & [ "TIME" , "ZONE" ] ) ?;
518+ }
519+ Ok ( Expr :: Value ( self . parse_timestamp_inner ( false ) ?) )
520+ }
521+
522+ fn parse_timestamptz ( & mut self ) -> Result < Expr , ParserError > {
523+ Ok ( Expr :: Value ( self . parse_timestamp_inner ( true ) ?) )
524+ }
525+
526+ fn parse_timestamp_inner ( & mut self , parse_timezone : bool ) -> Result < Value , ParserError > {
512527 use std:: convert:: TryInto ;
513528
514529 let value = self . parse_literal_string ( ) ?;
515- let pdt = Self :: parse_interval_string ( & value, & DateTimeField :: Year ) ?;
530+ let pdt = Self :: parse_timestamp_string ( & value, parse_timezone ) ?;
516531
517532 match (
518- pdt. year , pdt. month , pdt. day , pdt. hour , pdt. minute , pdt. second , pdt. nano ,
533+ pdt. year ,
534+ pdt. month ,
535+ pdt. day ,
536+ pdt. hour ,
537+ pdt. minute ,
538+ pdt. second ,
539+ pdt. nano ,
540+ pdt. timezone_offset_second ,
519541 ) {
520- ( Some ( year) , Some ( month) , Some ( day) , Some ( hour) , Some ( minute) , Some ( second) , nano) => {
542+ (
543+ Some ( year) ,
544+ Some ( month) ,
545+ Some ( day) ,
546+ Some ( hour) ,
547+ Some ( minute) ,
548+ Some ( second) ,
549+ nano,
550+ timezone_offset_second,
551+ ) => {
521552 let p_err = |e : std:: num:: TryFromIntError , field : & str | {
522553 ParserError :: ParserError ( format ! (
523554 "{} in date '{}' is invalid: {}" ,
@@ -555,6 +586,23 @@ impl Parser {
555586 if second > 60 {
556587 parser_err ! ( "Second in timestamp '{}' cannot be > 60: {}" , value, second) ?;
557588 }
589+
590+ if parse_timezone {
591+ return Ok ( Value :: TimestampTz (
592+ value,
593+ ParsedTimestamp {
594+ year,
595+ month,
596+ day,
597+ hour,
598+ minute,
599+ second,
600+ nano : nano. unwrap_or ( 0 ) ,
601+ timezone_offset_second : timezone_offset_second. unwrap_or ( 0 ) ,
602+ } ,
603+ ) ) ;
604+ }
605+
558606 Ok ( Value :: Timestamp (
559607 value,
560608 ParsedTimestamp {
@@ -565,6 +613,7 @@ impl Parser {
565613 minute,
566614 second,
567615 nano : nano. unwrap_or ( 0 ) ,
616+ timezone_offset_second : 0 ,
568617 } ,
569618 ) )
570619 }
@@ -773,6 +822,27 @@ impl Parser {
773822 datetime:: build_parsed_datetime ( & toks, leading_field, value)
774823 }
775824
825+ pub fn parse_timestamp_string (
826+ value : & str ,
827+ parse_timezone : bool ,
828+ ) -> Result < ParsedDateTime , ParserError > {
829+ if value. is_empty ( ) {
830+ return Err ( ParserError :: ParserError (
831+ "Timestamp string is empty!" . to_string ( ) ,
832+ ) ) ;
833+ }
834+
835+ let ( ts_string, tz_string) = datetime:: split_timestamp_string ( value) ;
836+
837+ let mut pdt = Self :: parse_interval_string ( ts_string, & DateTimeField :: Year ) ?;
838+ if !parse_timezone || tz_string. is_empty ( ) {
839+ return Ok ( pdt) ;
840+ }
841+
842+ pdt. timezone_offset_second = Some ( datetime:: parse_timezone_offset_second ( tz_string) ?) ;
843+ Ok ( pdt)
844+ }
845+
776846 /// Parses the parens following the `[ NOT ] IN` operator
777847 pub fn parse_in ( & mut self , expr : Expr , negated : bool ) -> Result < Expr , ParserError > {
778848 self . expect_token ( & Token :: LParen ) ?;
@@ -1554,6 +1624,7 @@ impl Parser {
15541624 }
15551625 Ok ( DataType :: Timestamp )
15561626 }
1627+ "TIMESTAMPTZ" => Ok ( DataType :: TimestampTz ) ,
15571628 "TIME" => {
15581629 if self . parse_keyword ( "WITH" ) {
15591630 self . expect_keywords ( & [ "TIME" , "ZONE" ] ) ?;
0 commit comments