LCOV - code coverage report
Current view: top level - json - JavaSqlTimestampHelper.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 47 53 88.7 %
Date: 2022-11-19 15:00:39 Functions: 3 3 100.0 %

          Line data    Source code
       1             : // Copyright 2008 Google Inc.
       2             : //
       3             : // Licensed under the Apache License, Version 2.0 (the "License");
       4             : // you may not use this file except in compliance with the License.
       5             : // You may obtain a copy of the License at
       6             : //
       7             : // http://www.apache.org/licenses/LICENSE-2.0
       8             : //
       9             : // Unless required by applicable law or agreed to in writing, software
      10             : // distributed under the License is distributed on an "AS IS" BASIS,
      11             : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      12             : // See the License for the specific language governing permissions and
      13             : // limitations under the License.
      14             : 
      15             : package com.google.gerrit.json;
      16             : 
      17             : import com.google.common.base.Splitter;
      18             : import java.sql.Timestamp;
      19             : import java.util.Calendar;
      20             : import java.util.List;
      21             : import java.util.TimeZone;
      22             : 
      23             : /** Utility to parse Timestamp from a string. */
      24             : public class JavaSqlTimestampHelper {
      25             : 
      26          13 :   private static final Splitter TIMESTAMP_SPLITTER = Splitter.on(" ");
      27          13 :   private static final Splitter DATE_SPLITTER = Splitter.on("-");
      28          13 :   private static final Splitter TIME_SPLITTER = Splitter.on(":");
      29             : 
      30             :   /**
      31             :    * Parse a string into a timestamp.
      32             :    *
      33             :    * <p>Note that {@link Timestamp}s have no timezone, so the result is relative to the UTC epoch.
      34             :    *
      35             :    * <p>Supports the format {@code yyyy-MM-dd[ HH:mm:ss[.SSS][ Z]]} where {@code Z} is a 4-digit
      36             :    * offset with sign, e.g. {@code -0500}.
      37             :    *
      38             :    * @param s input string.
      39             :    * @return resulting timestamp.
      40             :    */
      41             :   public static Timestamp parseTimestamp(String s) {
      42          13 :     List<String> components = TIMESTAMP_SPLITTER.splitToList(s);
      43          13 :     if (components.size() < 1 || components.size() > 3) {
      44           0 :       throw new IllegalArgumentException("Expected date and optional time: " + s);
      45             :     }
      46          13 :     String date = components.get(0);
      47          13 :     String time = components.size() >= 2 ? components.get(1) : null;
      48          13 :     int off = components.size() == 3 ? parseTimeZone(components.get(2)) : 0;
      49          13 :     List<String> dSplit = DATE_SPLITTER.splitToList(date);
      50          13 :     if (dSplit.size() != 3) {
      51           1 :       throw new IllegalArgumentException("Invalid date format: " + date);
      52             :     }
      53             :     int yy, mm, dd;
      54             :     try {
      55          13 :       yy = Integer.parseInt(dSplit.get(0));
      56          13 :       mm = Integer.parseInt(dSplit.get(1)) - 1;
      57          13 :       dd = Integer.parseInt(dSplit.get(2));
      58           1 :     } catch (NumberFormatException e) {
      59           1 :       throw new IllegalArgumentException("Invalid date format: " + date, e);
      60          13 :     }
      61             : 
      62             :     int hh, mi, ss, ns;
      63          13 :     if (time != null) {
      64          13 :       int p = time.indexOf('.');
      65             :       String t;
      66             :       double f;
      67             :       try {
      68          13 :         if (p >= 0) {
      69           9 :           t = time.substring(0, p);
      70           9 :           f = Double.parseDouble("0." + time.substring(p + 1));
      71             :         } else {
      72           5 :           t = time;
      73           5 :           f = 0;
      74             :         }
      75          13 :         List<String> tSplit = TIME_SPLITTER.splitToList(t);
      76          13 :         if (tSplit.size() != 3) {
      77           0 :           throw new IllegalArgumentException("Invalid time format: " + time);
      78             :         }
      79          13 :         hh = Integer.parseInt(tSplit.get(0));
      80          13 :         mi = Integer.parseInt(tSplit.get(1));
      81          13 :         ss = Integer.parseInt(tSplit.get(2));
      82          13 :         ns = (int) Math.round(f * 1e9);
      83           0 :       } catch (NumberFormatException e) {
      84           0 :         throw new IllegalArgumentException("Invalid time format: " + time, e);
      85          13 :       }
      86          13 :     } else {
      87           5 :       hh = 0;
      88           5 :       mi = 0;
      89           5 :       ss = 0;
      90           5 :       ns = 0;
      91             :     }
      92          13 :     Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
      93          13 :     calendar.set(yy, mm, dd, hh, mi, ss);
      94          13 :     Timestamp result = new Timestamp(calendar.toInstant().toEpochMilli() - off);
      95          13 :     result.setNanos(ns);
      96          13 :     return result;
      97             :   }
      98             : 
      99             :   private static int parseTimeZone(String s) {
     100           5 :     if (s.length() != 5 || (s.charAt(0) != '-' && s.charAt(0) != '+')) {
     101           0 :       throw new IllegalArgumentException("Invalid time zone: " + s);
     102             :     }
     103           5 :     for (int i = 1; i < s.length(); i++) {
     104           5 :       if (s.charAt(i) < '0' || s.charAt(i) > '9') {
     105           0 :         throw new IllegalArgumentException("Invalid time zone: " + s);
     106             :       }
     107             :     }
     108             :     int off =
     109           5 :         (s.charAt(0) == '-' ? -1 : 1)
     110             :             * 60
     111             :             * 1000
     112           5 :             * ((60 * Integer.parseInt(s.substring(1, 3))) + Integer.parseInt(s.substring(3, 5)));
     113           5 :     return off;
     114             :   }
     115             : 
     116             :   private JavaSqlTimestampHelper() {}
     117             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750