1 /*
2 * Copyright (c) 2012-2023, jcabi.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met: 1) Redistributions of source code must retain the above
8 * copyright notice, this list of conditions and the following
9 * disclaimer. 2) Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution. 3) Neither the name of the jcabi.com nor
13 * the names of its contributors may be used to endorse or promote
14 * products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 package com.jcabi.jdbc;
31
32 import java.sql.PreparedStatement;
33 import java.sql.ResultSet;
34 import java.sql.SQLException;
35 import java.sql.Timestamp;
36 import java.util.Calendar;
37 import java.util.Date;
38 import java.util.SimpleTimeZone;
39 import lombok.EqualsAndHashCode;
40 import lombok.ToString;
41
42 /**
43 * UTC time zone manipulator.
44 *
45 * <p>When it's necessary to save date/time to the DB in UTC timezone, use
46 * this class:
47 *
48 * <pre> new JdbcSession(source)
49 * .sql("INSERT INTO payment (amount, date) VALUES (?, ?)")
50 * .set(500)
51 * .set(new Utc()) // current date to be set, in UTC timezone
52 * .insert(Outcome.VOID);</pre>
53 *
54 * <p>This class also helps during date/time retrieval:
55 *
56 * <pre> Date date = new JdbcSession(source)
57 * .sql("SELECT date FROM payment WHERE id = 555")
58 * .select(
59 * new Outcome<Date>() {
60 * @Override
61 * public Date handle(final ResultSet rset) throws SQLException {
62 * return Utc.getTimestamp(rset, 1);
63 * }
64 * }
65 * );</pre>
66 *
67 * <p>{@link Timestamp} is used because {@link java.sql.Date}
68 * supports only dates (without time).
69 *
70 * @since 0.1.8
71 */
72 @ToString
73 @EqualsAndHashCode(of = "date")
74 public final class Utc {
75
76 /**
77 * The calendar to use.
78 */
79 private static final Calendar CALENDAR =
80 Calendar.getInstance(new SimpleTimeZone(0, "UTC"));
81
82 /**
83 * The date to work with.
84 */
85 private final transient long date;
86
87 /**
88 * Public ctor, with current date.
89 */
90 public Utc() {
91 this(new Date());
92 }
93
94 /**
95 * Public ctor.
96 * @param when The date to use.
97 */
98 public Utc(final Date when) {
99 this.date = when.getTime();
100 }
101
102 /**
103 * Get date that is encapsulated.
104 * @return The date
105 */
106 public Date getDate() {
107 return new Date(this.date);
108 }
109
110 /**
111 * Convert date to timestamp and save to the statement.
112 * @param stmt The statement
113 * @param pos Position in the statement
114 * @throws SQLException If some SQL problem inside
115 */
116 public void setTimestamp(final PreparedStatement stmt, final int pos)
117 throws SQLException {
118 stmt.setTimestamp(
119 pos,
120 new Timestamp(this.date),
121 Utc.CALENDAR
122 );
123 }
124
125 /**
126 * Retrieve timestamp from the result set.
127 * @param rset The result set
128 * @param pos Position in the result set
129 * @return The date
130 * @throws SQLException If some SQL problem inside
131 */
132 @SuppressWarnings("PMD.ProhibitPublicStaticMethods")
133 public static Date getTimestamp(final ResultSet rset, final int pos)
134 throws SQLException {
135 final Timestamp stamp = rset.getTimestamp(pos, Utc.CALENDAR);
136 Date when = null;
137 if (stamp != null) {
138 when = new Date(stamp.getTime());
139 }
140 return when;
141 }
142
143 }