📄 datetime.java
字号:
/* =============================================================
* SmallSQL : a free Java DBMS library for the Java(tm) platform
* =============================================================
*
* (C) Copyright 2004-2006, by Volker Berlin.
*
* Project Info: http://www.smallsql.de/
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* ---------------
* DateTime.java
* ---------------
* Author: Volker Berlin
*
* Created on 07.05.2004
*/
package smallsql.database;
import java.sql.*;
import java.text.DateFormatSymbols;
import java.util.Calendar;
import java.util.TimeZone;
public final class DateTime implements Mutable{
long time;
private int dataType = SQLTokenizer.TIMESTAMP;
static final int[] MONTH_DAYS = {0,31,59,90,120,151,181,212,243,273,304,334};
private static final String[] SHORT_MONTHS = new DateFormatSymbols().getShortMonths();
/* unused code
DateTime(final int year, final int month, final int day, final int hour, final int minute, final int second, final int millis){
time = calcMillis( year, month, day, hour, minute, second, millis);
}*/
DateTime(long time, int dataType){
switch(dataType){
case SQLTokenizer.SMALLDATETIME:
int seconds = (int)(time % 60000);
if(seconds < 0){
seconds += 60000;
}
time -= seconds;
break;
case SQLTokenizer.TIME:
time %= 86400000;
break;
case SQLTokenizer.DATE:
int millis = (int)(time % 86400000);
if(millis < 0)
millis += 86400000;
time -= millis;
break;
}
this.time = time;
this.dataType = dataType;
}
static long calcMillis(Details details){
return calcMillis(details.year, details.month, details.day, details.hour, details.minute, details.second, details.millis);
}
static long calcMillis(int year, int month, final int day, final int hour, final int minute, final int second, final int millis){
long result = millis;
result += second * 1000;
result += minute * 60000;
result += hour * 3600000;
result += (day-1) * 86400000L;
if(month > 11){
year += month / 12;
month %= 12;
}
result += MONTH_DAYS[month] * 86400000L;
result += (year - 1970) * 31536000000L; // millis 365 days
result += ((year/4) - (year/100) + (year/400) - 477) * 86400000L;
if(month<2 && year % 4 == 0 && (year%100 != 0 || year%400 == 0))
result -= 86400000L;
return result;
}
static long now(){
return removeDateTimeOffset( System.currentTimeMillis() );
}
/**
* Return the day of week.<p>
* 0 - Monday<p>
* 1 - Tuesday<p>
* 2 - Wednsday<p>
* 3 - Thursday<p>
* 4 - Friday<p>
* 5 - Saturday<p>
* 6 - Sunday<p>
*/
static int dayOfWeek(long time){
// the 1. Jan 1970 is a Thursday --> 3
return (int)((time / 86400000 + 3) % 7);
}
static long parse(java.util.Date date){
long t = date.getTime();
return removeDateTimeOffset(t);
}
static DateTime valueOf(java.util.Date date){
if(date == null) return null;
int type;
if(date instanceof java.sql.Date)
type = SQLTokenizer.DATE;
else
if(date instanceof java.sql.Time)
type = SQLTokenizer.TIME;
else
type = SQLTokenizer.TIMESTAMP;
return new DateTime( parse(date), type);
}
static DateTime valueOf(java.sql.Date date){
if(date == null) return null;
return new DateTime( parse(date), SQLTokenizer.DATE);
}
static DateTime valueOf(java.sql.Time date){
if(date == null) return null;
return new DateTime( parse(date), SQLTokenizer.TIME);
}
static DateTime valueOf(java.sql.Timestamp date){
if(date == null) return null;
return new DateTime( parse(date), SQLTokenizer.TIMESTAMP);
}
/**
* @param dataType is used for the toString() method
*/
static DateTime valueOf(String date, int dataType) throws SQLException{
if(date == null) return null;
return new DateTime( parse(date), dataType);
}
static long parse(final String datetime) throws SQLException{
try{
final int length = datetime.length();
final int year;
final int month;
final int day;
final int hour;
final int minute;
final int second;
final int millis;
int idx1 = 0;
int idx2 = datetime.indexOf('-');
if(idx2 > 0){
year = Integer.parseInt(datetime.substring(idx1, idx2).trim());
idx1 = idx2+1;
idx2 = datetime.indexOf('-', idx1);
month = Integer.parseInt(datetime.substring(idx1, idx2).trim())-1;
idx1 = idx2+1;
idx2 = datetime.indexOf(' ', idx1);
if(idx2 < 0) idx2 = datetime.length();
day = Integer.parseInt(datetime.substring(idx1, idx2).trim());
}else{
year = 1970;
month = 0;
day = 1;
}
idx1 = idx2+1;
idx2 = datetime.indexOf(':', idx1);
if(idx2>0){
hour = Integer.parseInt(datetime.substring(idx1, idx2).trim());
idx1 = idx2+1;
idx2 = datetime.indexOf(':', idx1);
minute = Integer.parseInt(datetime.substring(idx1, idx2).trim());
idx1 = idx2+1;
idx2 = datetime.indexOf('.', idx1);
if(idx2 < 0) idx2 = datetime.length();
second = Integer.parseInt(datetime.substring(idx1, idx2).trim());
idx1 = idx2+1;
if(idx1 < length){
String strMillis = datetime.substring(idx1).trim();
switch(strMillis.length()){
case 1:
millis = Integer.parseInt(strMillis) * 100;
break;
case 2:
millis = Integer.parseInt(strMillis) * 10;
break;
case 3:
millis = Integer.parseInt(strMillis);
break;
default:
millis = Integer.parseInt(strMillis.substring(0,3));
}
}else
millis = 0;
}else{
hour = 0;
minute = 0;
second = 0;
millis = 0;
}
if(idx1 == 0 && length > 0){
throw Utils.createSQLException("No valid Date or Time part." );
}
if(month >= 12){
throw Utils.createSQLException("Months are to large in DATE or TIMESTAMP value \"{0}\".", datetime );
}
if(day >= 32){
throw Utils.createSQLException("Days are to large in DATE or TIMESTAMP value \"{0}\".", datetime );
}
if(hour >= 24){
throw Utils.createSQLException("Hours are to large in TIME or TIMESTAMP value \"{0}\".", datetime );
}
if(minute >= 60){
throw Utils.createSQLException("Minutes are to large in TIME or TIMESTAMP value \"{0}\".", datetime );
}
if(second >= 60){
throw Utils.createSQLException("Seconds are to large in TIME or TIMESTAMP value \"{0}\".", datetime );
}
if(millis >= 1000){
throw Utils.createSQLException("Seconds are to large in TIMESTAMP value \"{0}\".", datetime );
}
return calcMillis(year, month, day, hour, minute, second, millis);
}catch(SQLException ex){
throw ex;
}catch(Throwable ex){
throw Utils.createSQLException('\'' +datetime+ "' is an invalid DATE, TIME or TIMESTAMP", ex );
}
}
long getTimeMillis(){
return time;
}
int getDataType(){
return dataType;
}
/**
* Convert the this value in a String depending of the type the format is a subset of
* yyyy-mm-dd hh:mm:ss.nnn
*/
public String toString(){
Details details = new Details(time);
StringBuffer buf = new StringBuffer();
if(dataType != SQLTokenizer.TIME){
formatNumber( details.year, 4, buf );
buf.append('-');
formatNumber( details.month + 1, 2, buf );
buf.append('-');
formatNumber( details.day, 2, buf );
}
if(dataType != SQLTokenizer.DATE){
if(buf.length() > 0) buf.append(' ');
formatNumber( details.hour, 2, buf );
buf.append(':');
formatNumber( details.minute, 2, buf );
buf.append(':');
formatNumber( details.second, 2, buf );
}
switch(dataType){
case SQLTokenizer.TIMESTAMP:
case SQLTokenizer.SMALLDATETIME:
buf.append('.');
formatMillis( details.millis, buf );
}
return buf.toString();
}
public boolean equals(Object obj){
if(!(obj instanceof DateTime)) return false;
DateTime value = (DateTime)obj;
return value.time == time && value.dataType == dataType;
}
/**
* @param style a value like the syle of CONVERT function from MS SQL Server.
*/
String toString(int style){
if(style < 0)
return toString();
Details details = new Details(time);
StringBuffer buf = new StringBuffer();
switch(style){
case 0:
case 100: // mon dd yyyy hh:miAM (oder PM)
buf.append( SHORT_MONTHS[ details.month ]);
buf.append(' ');
formatNumber( details.day, 2, buf);
buf.append(' ');
formatNumber( details.year, 4, buf);
buf.append(' ');
formatHour12( details.hour, buf );
buf.append(':');
formatNumber( details.minute, 2, buf);
buf.append( details.hour < 12 ? "AM" : "PM" );
return buf.toString();
case 1: // USA mm/dd/yy
formatNumber( details.month+1, 2, buf);
buf.append('/');
formatNumber( details.day, 2, buf);
buf.append('/');
formatNumber( details.year % 100, 2, buf);
return buf.toString();
case 101: // USA mm/dd/yyyy
formatNumber( details.month+1, 2, buf);
buf.append('/');
formatNumber( details.day, 2, buf);
buf.append('/');
formatNumber( details.year, 4, buf);
return buf.toString();
case 2: // ANSI yy.mm.dd
formatNumber( details.year % 100, 2, buf);
buf.append('.');
formatNumber( details.month+1, 2, buf);
buf.append('.');
formatNumber( details.day, 2, buf);
return buf.toString();
case 102: // ANSI yyyy.mm.dd
formatNumber( details.year, 4, buf);
buf.append('.');
formatNumber( details.month+1, 2, buf);
buf.append('.');
formatNumber( details.day, 2, buf);
return buf.toString();
case 3: // britsh dd/mm/yy
formatNumber( details.day, 2, buf);
buf.append('/');
formatNumber( details.month+1, 2, buf);
buf.append('/');
formatNumber( details.year % 100, 2, buf);
return buf.toString();
case 103: // britsh dd/mm/yyyy
formatNumber( details.day, 2, buf);
buf.append('/');
formatNumber( details.month+1, 2, buf);
buf.append('/');
formatNumber( details.year, 4, buf);
return buf.toString();
case 4: // german dd.mm.yy
formatNumber( details.day, 2, buf);
buf.append('.');
formatNumber( details.month+1, 2, buf);
buf.append('.');
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -