java.util.Date是常用的表示时间的类,我们通常格式化或者得到当前时间都用它。而在大多数数据库中,一般都支持三种形式的日期时间字段,即 DATE、TIME 和 TIMESTAMP。它们中的每一个在 JDBC 中都有一个对应的类,并且它们都扩展自java.util.Date。这三个类分别是:
- java.sql.Date表示 SQL DATE,存储年月日,没有时间组件。java.sql.Date 不考虑时区。
- java.sql.Time表示 SQL TIME,仅包含有关小时、分钟、秒和毫秒的信息,不包含日期组件。
- java.sql.Timestamp表示 SQL TIMESTAMP,它包含精确到纳秒精度的日期和时间信息。
1、日期类继承结构
日期类继承结构如下:
java.lang.Object
…|__java.util.Date
…|__java.sql.Date
…|__java.sql.Time
…|__java.sql.Timestamp
【父类】java.util.Date日期格式为:年月日时分秒。
【子类】java.sql.Date日期格式为:年月日,只存储日期数据不存储时间数据。
【子类】java.sql.Time日期格式为:时分秒。
【子类】java.sql.Timestamp日期格式为:年月日时分秒纳秒(毫微秒)。
5 个数据库日期时间数据类型:
Database | SQL DATE | SQL TIME | SQL TIMESTAMP |
---|---|---|---|
MySQL / MariaDB | DATE、DATETIME | TIME | TIMESTAMP |
PostgreSQL | DATE | TIME、TIME WITH TIME ZONE | TIMESTAMP、TIMESTAMP WITH TIME ZONE |
Oracle | DATE | TIMESTAMP、TIMESTAMP WITH TIME ZONE、TIMESTAMP WITH LOCAL TIME ZONE | |
Microsoft SQL Server | DATE、SMALLDATETIME、DATETIME、DATETIME2、DATETIMEOFFSET | TIME | |
IBM Db2 | DATE | TIME | TIMESTAMP |
2、JDBC下使用java.sql类型
JDBC操作数据库时,选择哪个类(java.sql.Date、java.sql.Time、java.sql.Timestamp)取决于字段的 SQL 类型。PreparedStatement 具有所有三个值的设置器,setDate() 用于 java.sql.Date,setTime() 用于 java.sql.Time,setTimestamp() 用于 java.sql.Timestamp。
下面以MySQL数据库为例,在数据库中创建一个测试表,同时有这3种数据类型对应的属性。
CREATE TABLE test_datetime (
dtm_date DATE,
dtm_time TIME,
dtm_timestamp TIMESTAMP,
obj_date DATE,
obj_time TIME,
obj_timestamp TIMESTAMP
);
然后我们将当前日期/时间(通过 new java.util.Date() 获取)插入到 SQL 数据库表的日期字段中。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class SqlDateTimeInsertExample {
public static void main(String[] args) throws Exception {
// (1) connect to mysql database
String url = "jdbc:mysql://localhost/coffeehouse?serverTimezone=Asia/Singapore";
Class.forName("com.mysql.cj.jdbc.Driver");
try (Connection conn = DriverManager.getConnection(url, "barista", "cappuccino")) {
// (2) set java.sql.Date, Time, and Timestamp with current Date (and time)
java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
java.sql.Time sqlTime = new java.sql.Time(utilDate.getTime());
java.sql.Timestamp sqlTS = new java.sql.Timestamp(utilDate.getTime());
// (3) insert java.sql.Date, Time and Timestamp (including objects) to DB
String sql = "INSERT INTO test_datetime("
+ "dtm_date, dtm_time, dtm_timestamp,"
+ "obj_date, obj_time, obj_timestamp) VALUES (?,?,?,?,?,?)";
try (PreparedStatement pst = conn.prepareStatement(sql)) {
pst.setDate(1, sqlDate);
pst.setTime(2, sqlTime);
pst.setTimestamp(3, sqlTS);
pst.setObject(4, utilDate);
pst.setObject(5, utilDate);
pst.setObject(6, utilDate);
// (4) execute update
pst.executeUpdate();
}
}
}
}
请注意上例中使用 setObject(int parameterIndex , x Object);
时可以只给最后三个参数一个 java.util.Date ,它们可以毫无问题地接受它,但是只是懒惰地使用 setObject(…) 会导致一些问题,如数据(或部分数据)丢失。
连接mysql确认结果:
$ mysql -u barista -p
Enter password: **********
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 5.5.27 MySQL Community Server (GPL)
mysql> connect coffeehouse
Connection id: 10
Current database: coffeehouse
mysql> select * from test_datetime;
+------------+----------+---------------------+------------+----------+---------------------+
| dtm_date | dtm_time | dtm_timestamp | obj_date | obj_time | obj_timestamp |
+------------+----------+---------------------+------------+----------+---------------------+
| 2022-08-15 | 16:48:19 | 2022-08-15 16:48:19 | 2022-08-15 | 16:48:19 | 2022-08-15 16:48:19 |
+------------+----------+---------------------+------------+----------+---------------------+
1 row in set (0.00 sec)
3、类型互转
java.util.Date、java.sql.Date、java.sql.Time、java.sql.Timestamp这四种对象内部均使用系统时间作为标准数据:
- 系统时间:自 1970 年 1 月 1 日 00:00:00 GMT 以来的毫秒数,即格林尼治标准时间GMT)
- 本地时间:根据时区不同打印出来的时间[当时区为GMT+0时,系统时间与本地时间相同]我们使用的是以本地时间为参考标准的。
3.1 java.util.Date与java.sql.Date互转
// 输出java.util.Date类
Date date = new Date();
System.out.println(date);
// 构造并输出java.sql.Date类
java.sql.Date sqlDate = new java.sql.Date(date.getTime());
System.out.println(sqlDate);
// java.sql.Date自动转型java.util.Date
Date utilDate = sqlDate;
System.out.println(utilDate);
// 构造并输出java.util.Date
utilDate = new java.util.Date(sqlDate.getTime());
System.out.println(utilDate);
- java.sql.Date是java.util.Date的子类,两者都有getTime方法返回毫秒数,自然就可以直接使用毫秒数构建。
- java.util.Date具有年月日时分秒,java.sql.Date类没有时分秒,只有年月日。
- java.util.Date类转java.sql.Date类,向下转型,需要调用java.util.Date类的getTime()方法,取得long类型返回值,作为参数转换。
- java.sql.Date类转java.util.Date类,向上转型,会自动转换,但是数值我们可以很明显的看到,也没有了时分秒。如果使用毫秒数构建,则输出值会有时间。
// java.sql.Date ==》 java.util.Date
java.sql.Date date = new java.sql.Date(2022,9,5);
java.util.Date d = new java.util.Date (date.getTime());
// java.util.Date ==》 java.sql.Date
java.util.Date utilDate = new Date();
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
3.2 java.util.Date与java.sql.Time互转
// 输出java.util.Date类
Date date = new Date();
System.out.println(date);
// 构造并输出java.sql.Time类
java.sql.Time sqlTime = new java.sql.Time(date.getTime());
System.out.println(sqlTime);
// java.sql.Time自动转型java.util.Time
Date utilDate = sqlTime;
System.out.println(utilDate);
// 构造并输出java.util.Date
utilDate = new java.util.Date(sqlTime.getTime());
System.out.println(utilDate);
3.3 java.util.Date与java.sql.Timestamp互转
// 输出java.util.Date类
Date date = new Date();
System.out.println(date);
// 构造并输出java.sql.Time类
java.sql.Timestamp sqlTimestamp = new java.sql.Timestamp(date.getTime());
System.out.println(sqlTimestamp);
// java.sql.Timestamp自动转型java.util.Time
Date utilDate = sqlTimestamp;
System.out.println(utilDate);
// 构造并输出java.util.Date
utilDate = new java.util.Date(sqlTimestamp.getTime());
System.out.println(utilDate);
类型互转例子
public static void test() throws ParseException {
//java.util.Date时间格式的转换
SimpleDateFormat f_utilDate=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String str="2022-5-31 14:40:50";
java.util.Date utilDate=f_utilDate.parse(str);
System.out.println(f_utilDate.format(utilDate));
//java.sql.Date时间格式的转换
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
System.out.println(f_utilDate.format(sqlDate));
SimpleDateFormat f_sqlDate=new SimpleDateFormat("yyyy-MM-dd");
sqlDate = java.sql.Date.valueOf("2022-08-20");
System.out.println(f_sqlDate.format(sqlDate));
java.util.Date utilDate1=new java.util.Date(sqlDate.getTime());
System.out.println(f_sqlDate.format(utilDate1));
//java.sql.Time sqltime时间格式的转换
SimpleDateFormat f_sqlTime=new SimpleDateFormat("hh:mm:ss");
java.sql.Time sqltime = java.sql.Time.valueOf("13:44:53");
System.out.println(f_sqlTime.format(sqltime));
sqltime = new java.sql.Time(new java.util.Date().getTime());
System.out.println(f_sqlTime.format(sqltime));
//java.sql.Timestamp时间格式的转换
SimpleDateFormat f_timestamp=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
java.sql.Timestamp timestamp = java.sql.Timestamp.valueOf("2022-08-20 14:06:27.186");
System.out.println(f_timestamp.format(timestamp));
timestamp = new java.sql.Timestamp(new java.util.Date().getTime());
System.out.println(f_timestamp.format(timestamp));
timestamp = new Timestamp(System.currentTimeMillis());
System.out.println(f_timestamp.format(timestamp));
}
4、使用实例
4.1 java.sql.Timestamp 的使用
/**
* 指定时间的日期是否为当前日期
*
* @param timestamp 指定时间
* @return
*/
public static boolean isCurrentDate(Timestamp timestamp){
String currentDate = format(new Date(), "yyyy-MM-dd");
String createDate = new SimpleDateFormat("yyyy-MM-dd").format(timestamp.getTime());
return currentDate.equals(createDate);
}
/**
* 指定时间的次日日期是否为当前日期
*
* @param timestamp 指定时间
* @return
*/
public static boolean isNextDateEqCurrentDate(Timestamp timestamp){
Calendar calendar = new GregorianCalendar();
calendar.setTime(timestamp);
calendar.add(calendar.DATE,1); //把日期往后增加一天
String nextDate = new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
String currentDate = format(new Date(), "yyyy-MM-dd");
return currentDate.equals(nextDate);
}
/**
* 获取指定时间的格式化字符串
* @param date 时间
* @param pattern 格式
* @return
*/
public static String format(Date date, String pattern) {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
String today = sdf.format(date);
return today;
}
4.2 java.sql.Time 的使用
/**
* 判断当前时间是否在指定的时间范围之内
*
* @param beginTime 开始时间,如10:00:00
* @param endTime 结束时间,如18:00:00
* @return
*/
public static boolean currentTimeIsWithinRange(Time beginTime, Time endTime) {
// 当前时间
Calendar currentDateTime = Calendar.getInstance();
// convert it to java epoch date
Date currentTime = new Date(Time.valueOf(new SimpleDateFormat("HH:mm:ss").format(currentDateTime.getTime())).getTime());
Date begin = new Date(beginTime.getTime());
Date end = new Date(endTime.getTime());
if(currentTime.after(begin) && currentTime.before(end)) {
return true;
}
return false;
}
/**
* 判断 timestamp 的 time部分 是否在 endTime 之前
*
* @param timestamp 需要判断的timestamp
* @param endTime
* @return
*/
public static boolean isBeforeEndTime(Timestamp timestamp, Time endTime) {
Date datetime = new Date(Time.valueOf(new SimpleDateFormat("HH:mm:ss").format(timestamp.getTime())).getTime());
Date end = new Date(endTime.getTime());
return datetime.before(end);
}
评论区