侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 285 篇文章
  • 累计创建 125 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

java.util.Date与java.sql.Date、java.sql.Time、java.sql.Timestamp的区别及应用

孔子说JAVA
2022-09-05 / 0 评论 / 0 点赞 / 35 阅读 / 8,499 字 / 正在检测是否收录...

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);

image-1662340816624

  • 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);

image-1662341368794

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);

image-1662341505832

类型互转例子

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);
}
0

评论区