@@ -212,7 +212,8 @@ impl Parser {
212
212
expr : Box :: new ( self . parse_subexpr ( Self :: UNARY_NOT_PREC ) ?) ,
213
213
} ) ,
214
214
"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 ( ) ,
216
217
// Here `w` is a word, check if it's a part of a multi-part
217
218
// identifier, a function call, or a simple identifier:
218
219
_ => match self . peek_token ( ) {
@@ -508,16 +509,46 @@ impl Parser {
508
509
}
509
510
}
510
511
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 > {
512
527
use std:: convert:: TryInto ;
513
528
514
529
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 ) ?;
516
531
517
532
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 ,
519
541
) {
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
+ ) => {
521
552
let p_err = |e : std:: num:: TryFromIntError , field : & str | {
522
553
ParserError :: ParserError ( format ! (
523
554
"{} in date '{}' is invalid: {}" ,
@@ -555,6 +586,23 @@ impl Parser {
555
586
if second > 60 {
556
587
parser_err ! ( "Second in timestamp '{}' cannot be > 60: {}" , value, second) ?;
557
588
}
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
+
558
606
Ok ( Value :: Timestamp (
559
607
value,
560
608
ParsedTimestamp {
@@ -565,6 +613,7 @@ impl Parser {
565
613
minute,
566
614
second,
567
615
nano : nano. unwrap_or ( 0 ) ,
616
+ timezone_offset_second : 0 ,
568
617
} ,
569
618
) )
570
619
}
@@ -773,6 +822,27 @@ impl Parser {
773
822
datetime:: build_parsed_datetime ( & toks, leading_field, value)
774
823
}
775
824
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
+
776
846
/// Parses the parens following the `[ NOT ] IN` operator
777
847
pub fn parse_in ( & mut self , expr : Expr , negated : bool ) -> Result < Expr , ParserError > {
778
848
self . expect_token ( & Token :: LParen ) ?;
@@ -1554,6 +1624,7 @@ impl Parser {
1554
1624
}
1555
1625
Ok ( DataType :: Timestamp )
1556
1626
}
1627
+ "TIMESTAMPTZ" => Ok ( DataType :: TimestampTz ) ,
1557
1628
"TIME" => {
1558
1629
if self . parse_keyword ( "WITH" ) {
1559
1630
self . expect_keywords ( & [ "TIME" , "ZONE" ] ) ?;
0 commit comments