/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.sql;
/**
* A class which can consume and produce dates in SQL {@code Date} format.
* <p>
* Dates are represented in SQL as {@code yyyy-MM-dd}. Note that this date
* format only deals with year, month and day values. There are no values for
* hours, minutes, seconds.
* <p>
* This is unlike the familiar {@code java.util.Date} object, which also includes
* values for hours, minutes, seconds, and milliseconds.
* <p>
* Time points are handled as millisecond values - milliseconds since the Epoch,
* January 1st 1970, 00:00:00.000 GMT. Time values passed to the {@code
* java.sql.Date} class are "normalized" to the time 00:00:00.000 GMT on the
* date implied by the time value.
*/
@FindBugsSuppressWarnings("NM_SAME_SIMPLE_NAME_AS_SUPERCLASS")
public class Date extends java.util.Date {
private static final long serialVersionUID = 1511598038487230103L;
/**
* Constructs a {@code Date} object corresponding to the supplied year,
* month and day.
*
* @deprecated Use the constructor {@link #Date(long)} instead.
* @param theYear
* the year, specified as the year minus 1900. Must be in the
* range {@code [0,8099]}.
* @param theMonth
* the month, specified as a number with 0 = January. Must be in
* the range {@code [0,11]}.
* @param theDay
* the day in the month. Must be in the range {@code [1,31]}.
*/
@Deprecated
public Date(int theYear, int theMonth, int theDay) {
super(theYear, theMonth, theDay);
}
/**
* Creates a date which corresponds to the day determined by the supplied
* milliseconds time value {@code theDate}.
*
* @param theDate
* a time value in milliseconds since the epoch - January 1 1970
* 00:00:00 GMT. The time value (hours, minutes, seconds,
* milliseconds) stored in the {@code Date} object is adjusted to
* correspond to 00:00:00 GMT on the day determined by the supplied
* time value.
*/
public Date(long theDate) {
super(normalizeTime(theDate));
}
/**
* @deprecated This method is deprecated and must not be used. SQL {@code
* Date} values do not have an hours component.
* @return does not return anything.
* @throws IllegalArgumentException
* if this method is called.
*/
@Deprecated
@Override
public int getHours() {
throw new IllegalArgumentException("unimplemented");
}
/**
* @deprecated This method is deprecated and must not be used. SQL {@code
* Date} values do not have a minutes component.
* @return does not return anything.
* @throws IllegalArgumentException
* if this method is called.
*/
@Deprecated
@Override
public int getMinutes() {
throw new IllegalArgumentException("unimplemented");
}
/**
* @deprecated This method is deprecated and must not be used. SQL {@code
* Date} values do not have a seconds component.
* @return does not return anything.
* @throws IllegalArgumentException
* if this method is called.
*/
@Deprecated
@Override
public int getSeconds() {
throw new IllegalArgumentException("unimplemented");
}
/**
* @deprecated This method is deprecated and must not be used. SQL {@code
* Date} values do not have an hours component.
* @param theHours
* the number of hours to set.
* @throws IllegalArgumentException
* if this method is called.
*/
@Deprecated
@Override
public void setHours(int theHours) {
throw new IllegalArgumentException("unimplemented");
}
/**
* @deprecated This method is deprecated and must not be used. SQL {@code
* Date} values do not have a minutes component.
* @param theMinutes
* the number of minutes to set.
* @throws IllegalArgumentException
* if this method is called.
*/
@Deprecated
@Override
public void setMinutes(int theMinutes) {
throw new IllegalArgumentException("unimplemented");
}
/**
* @deprecated This method is deprecated and must not be used. SQL {@code
* Date} values do not have a seconds component.
* @param theSeconds
* the number of seconds to set.
* @throws IllegalArgumentException
* if this method is called.
*/
@Deprecated
@Override
public void setSeconds(int theSeconds) {
throw new IllegalArgumentException("unimplemented");
}
/**
* Sets this date to a date supplied as a milliseconds value. The date is
* set based on the supplied time value and rounded to zero GMT for that day.
*
* @param theTime
* the time in milliseconds since the Epoch.
*/
@Override
public void setTime(long theTime) {
/*
* Store the Date based on the supplied time after removing any time
* elements finer than the day based on zero GMT
*/
super.setTime(normalizeTime(theTime));
}
/**
* Produces a string representation of the date in SQL format
*
* @return a string representation of the date in SQL format - {@code "yyyy-MM-dd"}.
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder(10);
format((getYear() + 1900), 4, sb);
sb.append('-');
format((getMonth() + 1), 2, sb);
sb.append('-');
format(getDate(), 2, sb);
return sb.toString();
}
private static final String PADDING = "0000";
/*
* Private method to format the time
*/
private void format(int date, int digits, StringBuilder sb) {
String str = String.valueOf(date);
if (digits - str.length() > 0) {
sb.append(PADDING.substring(0, digits - str.length()));
}
sb.append(str);
}
/**
* Creates a {@code Date} from a string representation of a date in SQL
* format.
*
* @param dateString
* the string representation of a date in SQL format - " {@code yyyy-MM-dd}".
* @return the {@code Date} object.
* @throws IllegalArgumentException
* if the format of the supplied string does not match the SQL
* format.
*/
public static Date valueOf(String dateString) {
if (dateString == null) {
throw new IllegalArgumentException("dateString == null");
}
if (dateString.length() > 10) {
// early fail to avoid parsing huge invalid strings
throw new IllegalArgumentException();
}
String[] parts = dateString.split("-");
if (parts.length != 3) {
throw new IllegalArgumentException();
}
int year = Integer.parsePositiveInt(parts[0]);
int month = Integer.parsePositiveInt(parts[1]);
int day = Integer.parsePositiveInt(parts[2]);
return new Date(year - 1900, month - 1, day);
}
/*
* Private method which normalizes a Time value, removing all low
* significance digits corresponding to milliseconds, seconds, minutes and
* hours, so that the returned Time value corresponds to 00:00:00 GMT on a
* particular day.
*/
private static long normalizeTime(long theTime) {
return theTime;
}
}