1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.dbunit.dataset.datatype;
23
24 import java.math.BigInteger;
25 import java.sql.PreparedStatement;
26 import java.sql.ResultSet;
27 import java.sql.SQLException;
28 import java.sql.Timestamp;
29 import java.sql.Types;
30 import java.time.LocalDateTime;
31 import java.time.format.DateTimeParseException;
32 import java.util.TimeZone;
33 import java.util.regex.Matcher;
34 import java.util.regex.Pattern;
35
36 import org.dbunit.dataset.ITable;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40
41
42
43
44
45
46 public class TimestampDataType extends AbstractDataType
47 {
48 private static final BigInteger ONE_BILLION = new BigInteger("1000000000");
49 private static final Pattern TIMEZONE_REGEX =
50 Pattern.compile("(.*)(?:\\W([+-][0-2][0-9][0-5][0-9]))");
51
52
53
54
55 private static final Logger logger =
56 LoggerFactory.getLogger(TimestampDataType.class);
57
58 TimestampDataType()
59 {
60 super("TIMESTAMP", Types.TIMESTAMP, Timestamp.class, false);
61 }
62
63
64
65
66 @Override
67 public Object typeCast(final Object value) throws TypeCastException
68 {
69 logger.debug("typeCast(value={}) - start", value);
70
71 if (value == null || value == ITable.NO_VALUE)
72 {
73 return null;
74 }
75
76 if (value instanceof java.sql.Timestamp)
77 {
78 return value;
79 }
80
81 if (value instanceof java.util.Date)
82 {
83 final java.util.Date date = (java.util.Date) value;
84 return new java.sql.Timestamp(date.getTime());
85 }
86
87 if (value instanceof Long)
88 {
89 final Long date = (Long) value;
90 return new java.sql.Timestamp(date);
91 }
92
93 if (value instanceof String)
94 {
95 String stringValue = value.toString();
96
97 if (isExtendedSyntax(stringValue))
98 {
99
100 try
101 {
102 final LocalDateTime datetime =
103 RELATIVE_DATE_TIME_PARSER.parse(stringValue);
104 return java.sql.Timestamp.valueOf(datetime);
105 } catch (IllegalArgumentException | DateTimeParseException e)
106 {
107 throw new TypeCastException(value, this, e);
108 }
109 }
110
111 String zoneValue = null;
112
113 final Matcher tzMatcher = TIMEZONE_REGEX.matcher(stringValue);
114 if (tzMatcher.matches() && tzMatcher.group(2) != null)
115 {
116 stringValue = tzMatcher.group(1);
117 zoneValue = tzMatcher.group(2);
118 }
119
120 Timestamp ts = null;
121 if (stringValue.length() == 10)
122 {
123 try
124 {
125 final long time =
126 java.sql.Date.valueOf(stringValue).getTime();
127 ts = new java.sql.Timestamp(time);
128 } catch (final IllegalArgumentException e)
129 {
130
131 }
132 }
133 if (ts == null)
134 {
135 try
136 {
137 ts = java.sql.Timestamp.valueOf(stringValue);
138 } catch (final IllegalArgumentException e)
139 {
140 throw new TypeCastException(value, this, e);
141 }
142 }
143
144
145 if (zoneValue != null)
146 {
147 final long tsTime = ts.getTime();
148
149 final TimeZone localTZ = java.util.TimeZone.getDefault();
150 final int offset = localTZ.getOffset(tsTime);
151 final BigInteger localTZOffset = BigInteger.valueOf(offset);
152 BigInteger time = BigInteger.valueOf(tsTime / 1000 * 1000)
153 .add(localTZOffset).multiply(ONE_BILLION)
154 .add(BigInteger.valueOf(ts.getNanos()));
155 final int hours = Integer.parseInt(zoneValue.substring(1, 3));
156 final int minutes = Integer.parseInt(zoneValue.substring(3, 5));
157 final BigInteger offsetAsSeconds =
158 BigInteger.valueOf((hours * 3600) + (minutes * 60));
159 final BigInteger offsetAsNanos =
160 offsetAsSeconds.multiply(BigInteger.valueOf(1000))
161 .multiply(ONE_BILLION);
162 if (zoneValue.charAt(0) == '+')
163 {
164 time = time.subtract(offsetAsNanos);
165 } else
166 {
167 time = time.add(offsetAsNanos);
168 }
169 final BigInteger[] components =
170 time.divideAndRemainder(ONE_BILLION);
171 ts = new Timestamp(components[0].longValue());
172 ts.setNanos(components[1].intValue());
173 }
174
175 return ts;
176 }
177
178 throw new TypeCastException(value, this);
179 }
180
181 @Override
182 public boolean isDateTime()
183 {
184 logger.debug("isDateTime() - start");
185
186 return true;
187 }
188
189 @Override
190 public Object getSqlValue(final int column, final ResultSet resultSet)
191 throws SQLException, TypeCastException
192 {
193 logger.debug("getSqlValue(column={}, resultSet={}) - start", column,
194 resultSet);
195 final Timestamp rawValue = resultSet.getTimestamp(column);
196 final Timestamp value = resultSet.wasNull() ? null : rawValue;
197 logger.debug("getSqlValue: column={}, value={}", column, value);
198 return value;
199 }
200
201 @Override
202 public void setSqlValue(final Object value, final int column,
203 final PreparedStatement statement)
204 throws SQLException, TypeCastException
205 {
206 logger.debug("setSqlValue(value={}, column={}, statement={}) - start",
207 value, column, statement);
208
209 statement.setTimestamp(column, (java.sql.Timestamp) typeCast(value));
210 }
211 }