/** * Licensed 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. * * Copyright 2012-2016 the original author or authors. */ package org.assertj.db.type; import java.sql.Date; import java.text.ParseException; import java.util.Calendar; /** * This class represents a date value in the database. * * @author RĂ©gis Pouiller * */ public class DateValue implements Comparable<DateValue>, DateValueContainer { /** * Day of the month. */ private final int dayOfTheMonth; /** * Month. */ private final int month; /** * Year. */ private final int year; /** * Indicates where there are the digits in the {@code String} for {@link DateValue#DateValue(String)}. */ private static final String DATE_FORMAT = "\\d\\d\\d\\d-\\d\\d-\\d\\d"; /** * Makes an instance of date value from a day of month, a month and an year. * * @param year Year. * @param month Month. * @param dayOfTheMonth Day of the month. * @return An instance of date value. */ public static DateValue of(int year, int month, int dayOfTheMonth) { return new DateValue(year, month, dayOfTheMonth); } /** * Makes an instance of date value from a {@code String} in format {@code yyyy-mm-dd}. * * @param date Date in {@code String} format ({@code yyyy-mm-dd}). * @throws NullPointerException If {@code date} is {@code null}. * @throws ParseException If {@code date} don't respect the {@code yyyy-mm-dd} format. * @return An instance of date value. */ public static DateValue parse(String date) throws ParseException { return new DateValue(date); } /** * Makes an instance of date value from a {@link Date}. * * @param date Date. * @throws NullPointerException If {@code date} is {@code null}. * @return An instance of date value. */ public static DateValue from(Date date) { return new DateValue(date); } /** * Makes an instance of date value from a {@link Calendar}. * * @param calendar Calendar. * @throws NullPointerException If {@code calendar} is {@code null}. * @return An instance of date value. * @since 1.1.0 */ public static DateValue from(Calendar calendar) { return new DateValue(calendar); } /** * Makes an instance of the date value corresponding to now. * * @return An instance of date value. * @since 1.1.0 */ public static DateValue now() { return from(Calendar.getInstance()); } /** * Constructor. * * @param year Year. * @param month Month. * @param dayOfTheMonth Day of the month. */ public DateValue(int year, int month, int dayOfTheMonth) { this.dayOfTheMonth = dayOfTheMonth; this.month = month; this.year = year; } /** * Constructor. * * @param date Date in {@code String} format ({@code yyyy-mm-dd}). * @throws NullPointerException If {@code date} is {@code null}. * @throws ParseException If {@code date} don't respect the {@code yyyy-mm-dd} format. */ public DateValue(String date) throws ParseException { if (date == null) { throw new NullPointerException("date should be not null"); } if (date.matches(DATE_FORMAT)) { year = Integer.parseInt(date.substring(0, 4)); month = Integer.parseInt(date.substring(5, 7)); dayOfTheMonth = Integer.parseInt(date.substring(8)); } else { throw new ParseException("date must respect yyyy-mm-dd format", date.length()); } } /** * Constructor. * * @param date Date. * @throws NullPointerException If {@code date} is {@code null}. */ public DateValue(Date date) { if (date == null) { throw new NullPointerException("date should be not null"); } Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(date.getTime()); dayOfTheMonth = calendar.get(Calendar.DAY_OF_MONTH); month = calendar.get(Calendar.MONTH) + 1; year = calendar.get(Calendar.YEAR); } /** * Constructor. * * @param calendar Calendar. * @throws NullPointerException If {@code calendar} is {@code null}. */ public DateValue(Calendar calendar) { if (calendar == null) { throw new NullPointerException("date should be not null"); } dayOfTheMonth = calendar.get(Calendar.DAY_OF_MONTH); month = calendar.get(Calendar.MONTH) + 1; year = calendar.get(Calendar.YEAR); } /** {@inheritDoc} */ @Override public DateValue getDate() { return this; } public boolean isMidnight() { return true; } /** * Returns the day of the month. * * @return The day of the month. */ public int getDayOfTheMonth() { return dayOfTheMonth; } /** * Returns the month. * * @return The month. */ public int getMonth() { return month; } /** * Returns the year. * * @return The year. */ public int getYear() { return year; } @Override public String toString() { return String.format("%4d-%02d-%02d", year, month, dayOfTheMonth); } @Override public boolean equals(Object obj) { if (obj instanceof DateValue) { DateValue dateValue = (DateValue) obj; return year == dateValue.year && month == dateValue.month && dayOfTheMonth == dateValue.dayOfTheMonth; } else if (obj instanceof DateValueContainer) { DateValueContainer value = (DateValueContainer) obj; return equals(value.getDate()) && value.isMidnight(); } return false; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + dayOfTheMonth; result = prime * result + month; result = prime * result + year; return result; } @Override public int compareTo(DateValue other) { if (year < other.year) { return -1; } else if (year > other.year) { return 1; } else if (month < other.month) { return -1; } else if (month > other.month) { return 1; } else if (dayOfTheMonth < other.dayOfTheMonth) { return -1; } else if (dayOfTheMonth > other.dayOfTheMonth) { return 1; } return 0; } /** * Returns if this date value is before the date value in parameter. * @param date The date value to compare to. * @return If this date value is before the date value in parameter. */ public boolean isBefore(DateValue date) { return compareTo(date) == -1; } /** * Returns if this date value is after the date value in parameter. * @param date The date value to compare to. * @return If this date value is after the date value in parameter. */ public boolean isAfter(DateValue date) { return compareTo(date) == 1; } /** * Moves the date with the value in parameter. * @param date Value to move the date. * @return The date moved. */ public DateValue move(DateValue date) { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.YEAR, year); calendar.set(Calendar.MONTH, month - 1); calendar.set(Calendar.DAY_OF_MONTH, dayOfTheMonth); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); if (date.getYear() != 0) { calendar.add(Calendar.YEAR, date.getYear()); } if (date.getMonth() != 0) { calendar.add(Calendar.MONTH, date.getMonth()); } if (date.getDayOfTheMonth() != 0) { calendar.add(Calendar.DAY_OF_MONTH, date.getDayOfTheMonth()); } return from(calendar); } /** * Moves the date with the value in parameter. * @param time Value to move the date. * @return The date/time moved. */ public DateTimeValue move(TimeValue time) { TimeValue timeValue = TimeValue.of(0, 0); TimeValue movedTimeValue = timeValue.move(time); int hours = movedTimeValue.getHours(); int days = hours / 24; if (hours > 0) { hours -= days * 24; } else { hours += days * 24; } if (hours < 0) { days--; hours += 24; } DateValue dateValue = getDate(); DateValue movedDateValue = dateValue.move(DateValue.of(0, 0, days)); return DateTimeValue.of(movedDateValue, TimeValue.of(hours, movedTimeValue.getMinutes(), movedTimeValue.getSeconds(), movedTimeValue.getNanoSeconds())); } /** * Moves the date with the value in parameter. * @param dateTime Value to move the date. * @return The date/time moved. */ public DateTimeValue move(DateTimeValue dateTime) { DateValue date = move(dateTime.getDate()); return date.move(dateTime.getTime()); } /** * Returns the reverse of the date. * @return The reverse. */ public DateValue reverse() { return of(-getYear(), -getMonth(), -getDayOfTheMonth()); } }