/** * == @Spearal ==> * * Copyright (C) 2014 Franck WOLFF & William DRAI (http://www.spearal.io) * * 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. */ package org.spearal.impl; import java.sql.Time; import java.sql.Timestamp; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.Locale; import java.util.TimeZone; /** * @author Franck WOLFF */ public class SpearalDateTime { public static final TimeZone UTC = TimeZone.getTimeZone("UTC"); public final boolean hasDate; public final boolean hasTime; public final int year; public final int month; public final int date; public final int hours; public final int minutes; public final int seconds; public final int nanoseconds; public static SpearalDateTime forDate(int year, int month, int date) { return new SpearalDateTime(year, month, date, 0, 0, 0, 0, true, false); } public static SpearalDateTime forTime(int hours, int minutes, int seconds) { return new SpearalDateTime(0, 0, 0, hours, minutes, seconds, 0, false, true); } public static SpearalDateTime forTime(int hours, int minutes, int seconds, int nanoseconds) { return new SpearalDateTime(0, 0, 0, hours, minutes, seconds, nanoseconds, false, true); } public static SpearalDateTime forDate(Date date) { GregorianCalendar calendar = new GregorianCalendar(UTC, Locale.US); calendar.setTimeInMillis(date.getTime()); return new SpearalDateTime( calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DATE), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND), calendar.get(Calendar.MILLISECOND) * 1000000, true, true ); } public static SpearalDateTime forSQLDate(java.sql.Date date) { GregorianCalendar calendar = new GregorianCalendar(UTC, Locale.US); calendar.setTimeInMillis(date.getTime()); return new SpearalDateTime( calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DATE), 0, 0, 0, 0, true, false ); } public static SpearalDateTime forSQLTime(Time time) { GregorianCalendar calendar = new GregorianCalendar(UTC, Locale.US); calendar.setTimeInMillis(time.getTime()); return new SpearalDateTime( 0, 0, 0, calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND), 0, false, true ); } public static SpearalDateTime forSQLTimestamp(Timestamp timestamp) { GregorianCalendar calendar = new GregorianCalendar(UTC, Locale.US); calendar.setTimeInMillis(timestamp.getTime()); return new SpearalDateTime( calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DATE), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND), timestamp.getNanos(), true, true ); } public static SpearalDateTime forCalendar(Calendar calendar) { if (!(calendar instanceof GregorianCalendar)) { calendar = new GregorianCalendar(UTC, Locale.US); calendar.setTimeInMillis(calendar.getTimeInMillis()); } return forGregorianCalendar((GregorianCalendar)calendar); } public static SpearalDateTime forGregorianCalendar(GregorianCalendar calendar) { calendar.setTimeZone(UTC); int year = calendar.get(Calendar.YEAR); if (calendar.get(Calendar.ERA) == GregorianCalendar.BC) year = -year; return new SpearalDateTime( year, calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DATE), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND), calendar.get(Calendar.MILLISECOND) * 1000000, true, true ); } @SuppressWarnings("boxing") public SpearalDateTime( int year, int month, int date, int hours, int minutes, int seconds, int nanoseconds, boolean hasDate, boolean hasTime) { if (hasDate) { if (year < -999999999 || year > 999999999) throw new IllegalArgumentException("Illegal year: " + year); if (month < 1 || month > 12) throw new IllegalArgumentException("Illegal month: " + month); if (date < 1 || date > 31) throw new IllegalArgumentException("Illegal date: " + date); } else { year = 0; month = 0; date = 0; } if (hasTime) { if (hours < 0 || hours > 23) { if (hours == 24 && !(minutes == 0 && seconds == 0 && nanoseconds == 0)) throw new IllegalArgumentException(String.format("Illegal time: %02d:%02d:%02d.%09d", hours, minutes, seconds, nanoseconds)); throw new IllegalArgumentException("Illegal hours: " + hours); } if (minutes < 0 || minutes > 59) throw new IllegalArgumentException("Illegal minutes: " + minutes); if (seconds < 0 || seconds > 59) throw new IllegalArgumentException("Illegal seconds: " + seconds); if (nanoseconds < 0 || nanoseconds > 999999999) throw new IllegalArgumentException("Illegal nanoseconds: " + nanoseconds); } else { hours = 0; minutes = 0; seconds = 0; nanoseconds = 0; } this.hasDate = hasDate; this.hasTime = hasTime; this.year = year; this.month = month; this.date = date; this.hours = hours; this.minutes = minutes; this.seconds = seconds; this.nanoseconds = nanoseconds; } public GregorianCalendar toGregorianCalendar() { GregorianCalendar calendar = new GregorianCalendar(UTC, Locale.US); calendar.clear(); if (hasDate) { int year = this.year; if (year < 0) { year = -year; calendar.set(Calendar.ERA, GregorianCalendar.BC); } calendar.set(Calendar.YEAR, year); calendar.set(Calendar.MONTH, month - 1); calendar.set(Calendar.DATE, date); } if (hasTime) { calendar.set(Calendar.HOUR_OF_DAY, hours); calendar.set(Calendar.MINUTE, minutes); calendar.set(Calendar.SECOND, seconds); calendar.set(Calendar.MILLISECOND, nanoseconds / 1000000); } return calendar; } public Date toDate() { return toGregorianCalendar().getTime(); } public java.sql.Date toSQLDate() { return new java.sql.Date(toGregorianCalendar().getTime().getTime()); } public Time toSQLTime() { return new Time(toGregorianCalendar().getTime().getTime()); } public Timestamp toSQLTimestamp() { Timestamp timestamp = new Timestamp(toGregorianCalendar().getTime().getTime()); timestamp.setNanos(nanoseconds); return timestamp; } @SuppressWarnings("boxing") @Override public String toString() { return String.format( "%+010d-%02d-%02dT%02d:%02d:%02d.%09dZ", year, month, date, hours, minutes, seconds, nanoseconds ); } }