1 /* 2 * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.sql; 27 28 import java.time.Instant; 29 import java.time.LocalDate; 30 31 /** 32 * <P>A thin wrapper around a millisecond value that allows 33 * JDBC to identify this as an SQL <code>DATE</code> value. A 34 * milliseconds value represents the number of milliseconds that 35 * have passed since January 1, 1970 00:00:00.000 GMT. 36 * <p> 37 * To conform with the definition of SQL <code>DATE</code>, the 38 * millisecond values wrapped by a <code>java.sql.Date</code> instance 39 * must be 'normalized' by setting the 40 * hours, minutes, seconds, and milliseconds to zero in the particular 41 * time zone with which the instance is associated. 42 * 43 * @since 1.1 44 */ 45 public class Date extends java.util.Date { 46 47 /** 48 * Constructs a <code>Date</code> object initialized with the given 49 * year, month, and day. 50 * <P> 51 * The result is undefined if a given argument is out of bounds. 52 * 53 * @param year the year minus 1900; must be 0 to 8099. (Note that 54 * 8099 is 9999 minus 1900.) 55 * @param month 0 to 11 56 * @param day 1 to 31 57 * @deprecated instead use the constructor <code>Date(long date)</code> 58 */ 59 @Deprecated(since="1.2") Date(int year, int month, int day)60 public Date(int year, int month, int day) { 61 super(year, month, day); 62 } 63 64 /** 65 * Constructs a <code>Date</code> object using the given milliseconds 66 * time value. If the given milliseconds value contains time 67 * information, the driver will set the time components to the 68 * time in the default time zone (the time zone of the Java virtual 69 * machine running the application) that corresponds to zero GMT. 70 * 71 * @param date milliseconds since January 1, 1970, 00:00:00 GMT not 72 * to exceed the milliseconds representation for the year 8099. 73 * A negative number indicates the number of milliseconds 74 * before January 1, 1970, 00:00:00 GMT. 75 */ Date(long date)76 public Date(long date) { 77 // If the millisecond date value contains time info, mask it out. 78 super(date); 79 80 } 81 82 /** 83 * Sets an existing <code>Date</code> object 84 * using the given milliseconds time value. 85 * If the given milliseconds value contains time information, 86 * the driver will set the time components to the 87 * time in the default time zone (the time zone of the Java virtual 88 * machine running the application) that corresponds to zero GMT. 89 * 90 * @param date milliseconds since January 1, 1970, 00:00:00 GMT not 91 * to exceed the milliseconds representation for the year 8099. 92 * A negative number indicates the number of milliseconds 93 * before January 1, 1970, 00:00:00 GMT. 94 */ setTime(long date)95 public void setTime(long date) { 96 // If the millisecond date value contains time info, mask it out. 97 super.setTime(date); 98 } 99 100 /** 101 * Converts a string in JDBC date escape format to 102 * a <code>Date</code> value. 103 * 104 * @param s a <code>String</code> object representing a date in 105 * in the format "yyyy-[m]m-[d]d". The leading zero for <code>mm</code> 106 * and <code>dd</code> may also be omitted. 107 * @return a <code>java.sql.Date</code> object representing the 108 * given date 109 * @throws IllegalArgumentException if the date given is not in the 110 * JDBC date escape format (yyyy-[m]m-[d]d) 111 */ valueOf(String s)112 public static Date valueOf(String s) { 113 if (s == null) { 114 throw new java.lang.IllegalArgumentException(); 115 } 116 final int YEAR_LENGTH = 4; 117 final int MONTH_LENGTH = 2; 118 final int DAY_LENGTH = 2; 119 final int MAX_MONTH = 12; 120 final int MAX_DAY = 31; 121 Date d = null; 122 123 int firstDash = s.indexOf('-'); 124 int secondDash = s.indexOf('-', firstDash + 1); 125 int len = s.length(); 126 127 if ((firstDash > 0) && (secondDash > 0) && (secondDash < len - 1)) { 128 if (firstDash == YEAR_LENGTH && 129 (secondDash - firstDash > 1 && secondDash - firstDash <= MONTH_LENGTH + 1) && 130 (len - secondDash > 1 && len - secondDash <= DAY_LENGTH + 1)) { 131 int year = Integer.parseInt(s, 0, firstDash, 10); 132 int month = Integer.parseInt(s, firstDash + 1, secondDash, 10); 133 int day = Integer.parseInt(s, secondDash + 1, len, 10); 134 135 if ((month >= 1 && month <= MAX_MONTH) && (day >= 1 && day <= MAX_DAY)) { 136 d = new Date(year - 1900, month - 1, day); 137 } 138 } 139 } 140 if (d == null) { 141 throw new java.lang.IllegalArgumentException(); 142 } 143 144 return d; 145 146 } 147 148 149 /** 150 * Formats a date in the date escape format yyyy-mm-dd. 151 * 152 * @return a String in yyyy-mm-dd format 153 */ 154 @SuppressWarnings("deprecation") toString()155 public String toString () { 156 int year = super.getYear() + 1900; 157 int month = super.getMonth() + 1; 158 int day = super.getDate(); 159 160 char buf[] = new char[10]; 161 formatDecimalInt(year, buf, 0, 4); 162 buf[4] = '-'; 163 Date.formatDecimalInt(month, buf, 5, 2); 164 buf[7] = '-'; 165 Date.formatDecimalInt(day, buf, 8, 2); 166 167 return new String(buf); 168 } 169 170 /** 171 * Formats an unsigned integer into a char array in decimal output format. 172 * Numbers will be zero-padded or truncated if the string representation 173 * of the integer is smaller than or exceeds len, respectively. 174 * 175 * Should consider moving this to Integer and expose it through 176 * JavaLangAccess similar to Integer::formatUnsignedInt 177 * @param val Value to convert 178 * @param buf Array containing converted value 179 * @param offset Starting pos in buf 180 * @param len length of output value 181 */ formatDecimalInt(int val, char[] buf, int offset, int len)182 static void formatDecimalInt(int val, char[] buf, int offset, int len) { 183 int charPos = offset + len; 184 do { 185 buf[--charPos] = (char)('0' + (val % 10)); 186 val /= 10; 187 } while (charPos > offset); 188 } 189 190 // Override all the time operations inherited from java.util.Date; 191 192 /** 193 * This method is deprecated and should not be used because SQL Date 194 * values do not have a time component. 195 * 196 * @deprecated 197 * @exception java.lang.IllegalArgumentException if this method is invoked 198 * @see #setHours 199 */ 200 @Deprecated(since="1.2") getHours()201 public int getHours() { 202 throw new java.lang.IllegalArgumentException(); 203 } 204 205 /** 206 * This method is deprecated and should not be used because SQL Date 207 * values do not have a time component. 208 * 209 * @deprecated 210 * @exception java.lang.IllegalArgumentException if this method is invoked 211 * @see #setMinutes 212 */ 213 @Deprecated(since="1.2") getMinutes()214 public int getMinutes() { 215 throw new java.lang.IllegalArgumentException(); 216 } 217 218 /** 219 * This method is deprecated and should not be used because SQL Date 220 * values do not have a time component. 221 * 222 * @deprecated 223 * @exception java.lang.IllegalArgumentException if this method is invoked 224 * @see #setSeconds 225 */ 226 @Deprecated(since="1.2") getSeconds()227 public int getSeconds() { 228 throw new java.lang.IllegalArgumentException(); 229 } 230 231 /** 232 * This method is deprecated and should not be used because SQL Date 233 * values do not have a time component. 234 * 235 * @deprecated 236 * @exception java.lang.IllegalArgumentException if this method is invoked 237 * @see #getHours 238 */ 239 @Deprecated(since="1.2") setHours(int i)240 public void setHours(int i) { 241 throw new java.lang.IllegalArgumentException(); 242 } 243 244 /** 245 * This method is deprecated and should not be used because SQL Date 246 * values do not have a time component. 247 * 248 * @deprecated 249 * @exception java.lang.IllegalArgumentException if this method is invoked 250 * @see #getMinutes 251 */ 252 @Deprecated(since="1.2") setMinutes(int i)253 public void setMinutes(int i) { 254 throw new java.lang.IllegalArgumentException(); 255 } 256 257 /** 258 * This method is deprecated and should not be used because SQL Date 259 * values do not have a time component. 260 * 261 * @deprecated 262 * @exception java.lang.IllegalArgumentException if this method is invoked 263 * @see #getSeconds 264 */ 265 @Deprecated(since="1.2") setSeconds(int i)266 public void setSeconds(int i) { 267 throw new java.lang.IllegalArgumentException(); 268 } 269 270 /** 271 * Private serial version unique ID to ensure serialization 272 * compatibility. 273 */ 274 static final long serialVersionUID = 1511598038487230103L; 275 276 /** 277 * Obtains an instance of {@code Date} from a {@link LocalDate} object 278 * with the same year, month and day of month value as the given 279 * {@code LocalDate}. 280 * <p> 281 * The provided {@code LocalDate} is interpreted as the local date 282 * in the local time zone. 283 * 284 * @param date a {@code LocalDate} to convert 285 * @return a {@code Date} object 286 * @exception NullPointerException if {@code date} is null 287 * @since 1.8 288 */ 289 @SuppressWarnings("deprecation") valueOf(LocalDate date)290 public static Date valueOf(LocalDate date) { 291 return new Date(date.getYear() - 1900, date.getMonthValue() -1, 292 date.getDayOfMonth()); 293 } 294 295 /** 296 * Creates a {@code LocalDate} instance using the year, month and day 297 * from this {@code Date} object. 298 * @return a {@code LocalDate} object representing the same date value 299 * 300 * @since 1.8 301 */ 302 @SuppressWarnings("deprecation") toLocalDate()303 public LocalDate toLocalDate() { 304 return LocalDate.of(getYear() + 1900, getMonth() + 1, getDate()); 305 } 306 307 /** 308 * This method always throws an UnsupportedOperationException and should 309 * not be used because SQL {@code Date} values do not have a time 310 * component. 311 * 312 * @exception java.lang.UnsupportedOperationException if this method is invoked 313 */ 314 @Override toInstant()315 public Instant toInstant() { 316 throw new java.lang.UnsupportedOperationException(); 317 } 318 } 319