一、mysql中的时间数据类型
解释:
1、在 MySQL 中创建表时,对照上面的表格,很容易就能选择到合适自己的数据类型。不过到底是选择 datetime 还是 timestamp,可能会有点犯难。这两个日期时间类型各有优点:datetime 的日期范围比较大;timestamp 所占存储空间比较小,只是 datetime 的一半。 个人倾向于使用 datetime 日期类型。
2、timestamp 类型的列还有个特性:默认情况下,在 insert, update 数据时,timestamp 列会自动以当前时间(CURRENT_TIMESTAMP)填充/更新。“自动”的意思就是,你不去管它,MySQL 会替你去处理;而其他时间类型不会。
2、timestamp 类型的列还有个特性:默认情况下,在 insert, update 数据时,timestamp 列会自动以当前时间(CURRENT_TIMESTAMP)填充/更新。“自动”的意思就是,你不去管它,MySQL 会替你去处理;而其他时间类型不会。
3、time 时间的取值范围很大,特别是 time 可以取负值。看了 MySQL 手册发现这是为了满足两个日期时间相减才这样设计的。
select timediff('2000:01:31 23:59:59', '2000:01:01 00:00:00'); -- 743:59:59
select timediff('2000:01:01 00:00:00', '2000:01:31 23:59:59'); -- -743:59:59
select timediff('23:59:59', '12:00:00'); -- 11:59:59
注意,timediff 的两个参数只能是 datetime/timestamp, time 类型的,并且这两个参数类型要相同。即:datetime/timestamp 和 datetime/timestamp 比较;time 和 time 相比较。
二、java代码与数据库时间字段读写
1、实例
在说明之前,我们先来做个例子:
①在数据库中创建表“date_and_time”,除id外,其他字段是数据库中各类型的时间字段
并添加一条数据:
②在程序中查询该条数据,并打印每个字段的数据类型,调用代码如下:
//数据库连接代码省略
//查询
findPst = conn.prepareStatement("select * from date_and_time where id=?");
findPst.setInt(1, 8);
ResultSet rs = findPst.executeQuery();
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
while(rs.next()){
for (int i=1; i<=columnCount; i++) {
Object obj = rs.getObject(i);
//打印字段名称、字段内容、字段的数据类型
System.out.println(rsmd.getColumnName(i)+":"+obj+","+obj.getClass());
}
}
③在控制台输出,打印结果如下:
id:1,class java.lang.Integer
dateDemo:2017-06-22,class java.sql.Date
datetimeDemo:2017-06-22 15:33:08.0,class java.sql.Timestamp
timestampDemo:2017-06-22 15:33:08.0,class java.sql.Timestamp
timeDemo:15:33:08,class java.sql.Time
yearDemo:1990-01-01,class java.sql.Date
④从打印结果可以看出,数据库的时间类型,对应的都是java.sql.*包下面的类。对应关系如下表:
//连接数据库、获取结果集的代码略过
while(rs.next()){
for (int i=2; i<=columnCount; i++) {
java.sql.Date obj = rs.getDate(i);
//打印字段名称、字段内容、字段的数据类型
System.out.println(rsmd.getColumnName(i)+":"+obj+","+obj.getClass());
Timestamp timestamp = rs.getTimestamp(i);
System.out.println(rsmd.getColumnName(i)+":"+timestamp+","+timestamp.getClass());
}
}
dateDemo:2017-06-22,class java.sql.Date
dateDemo:2017-06-22 00:00:00.0,class java.sql.Timestamp
datetimeDemo:2017-06-22,class java.sql.Date
datetimeDemo:2017-06-22 15:33:08.0,class java.sql.Timestamp
timestampDemo:2017-06-22,class java.sql.Date
timestampDemo:2017-06-22 15:33:08.0,class java.sql.Timestamp
timeDemo:1970-01-01,class java.sql.Date
timeDemo:1970-01-01 15:33:08.0,class java.sql.Timestamp
yearDemo:1990-01-01,class java.sql.Date
yearDemo:1990-01-01 00:00:00.0,class java.sql.Timestamp
getTime() 方法不能取出year类型的字段,其他字段可以获取并转化类型。
dateDemo:00:00:00,class java.sql.Time
datetimeDemo:15:33:08,class java.sql.Time
timestampDemo:15:33:08,class java.sql.Time
timeDemo:15:33:08,class java.sql.Time
当然也可以通过getString()方法,将字段都转化成字符串。
datetimeDemo:2017-06-22 15:33:08.0,class java.lang.String
timestampDemo:2017-06-22 15:33:08.0,class java.lang.String
timeDemo:15:33:08,class java.lang.String
yearDemo:1990-01-01,class java.lang.String
通过结果和源码可以看出,都是先将字段变为对应的java类型,然后转化成String类型。
2、java.util.Date和java.sql.Date、Time、Timestamp
java.sqlDate,Time,Timestamp三个类有共同的父类,就是java.util.Date。它们的日期格式如下 (其实通过上面的例子也可以看出格式) :
java.util.Date日期格式为:年月日时分秒
java.sql.Date日期格式为:年月日
java.sql.Time日期格式为:时分秒
java.sql.Timestamp日期格式为:年月日时分秒纳秒(毫微秒)
相互之间可以通过转换成“long”类型,进行转换
java.util.Date utildate = new java.util.Date();
System.out.println("utildate:"+utildate);
java.sql.Date sqlDate = new java.sql.Date(utildate.getTime());
System.out.println("sqlDate:"+sqlDate);
java.sql.Time sqlTime = new java.sql.Time(utildate.getTime());
System.out.println("sqlTime:"+sqlTime);
java.sql.Timestamp sqlTimestamp = new java.sql.Timestamp(utildate.getTime());
System.out.println("sqlTimestamp:"+sqlTimestamp);
utildate:Fri Jun 23 17:16:02 CST 2017
sqlDate:2017-06-23
sqlTime:17:16:02
sqlTimestamp:2017-06-23 17:16:02.843
3、写入数据库
将程序中的日期和时间数据写入数据库中,有以下几个方式:
①像上面一样,通过java.util.Date转化为对应类型的数据,进行保存和写入:
pst = conn.prepareStatement("INSERT INTO date_and_time(`dateDemo`,`datetimeDemo`,`timestampDemo`,`timeDemo`,`yearDemo`) VALUES (?,?,?,?,?)");
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 sqlTimestamp = new java.sql.Timestamp(utildate.getTime());
//添加参数
pst.setDate(1,sqlDate);
pst.setTimestamp(2,sqlTimestamp);
pst.setTimestamp(3,sqlTimestamp);
pst.setTime(4,sqlTime);
pst.setInt(5, 11);
pst.executeUpdate();
注:YEAR(1byte)年份类型。允许的值是1901到2155,MySQL以YYYY格式来显示YEAR值,但是允许你把使用字符串或数字值赋给YEAR列。
②或者不用转化,直接使用java.util.Date
pst.setObject(1,new Date());
pst.setObject(2,new Date());
pst.setObject(3,new Date());
pst.setObject(4,new Date());
pst.setInt(5, 2011);
③也可以使用字符串类型,但格式必须正确,格式不正确会报com.mysql.jdbc.MysqlDataTruncation异常。
pst.setObject(1,"2017-1-1");
pst.setObject(2,"2017-10-05 10:10:10");
pst.setObject(3,"2017-5-05 10:10:10");
pst.setObject(4,"23:59:59");
pst.setInt(5, 11);
pst.executeUpdate();
三、java.util.Calendar与java.text.SimpleDateFormat
除了上面说的 java.sqlDate,Time,Timestamp和java.util.Date类外,还有两个与时间有关的类,那就是java.util.Calenda和java.text.SimpleDateFormat。
1、Calendar
java.util.Calendar['kælɪndə] 类(日历类):Calendar类是一个抽象基类,主要用于日期之间的各种计算。它为特定瞬间与一组诸如
YEAR
、MONTH
、DAY_OF_MONTH
、HOUR
等 日历字段
之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。
获取Calendar实例的方法:
Calendar
提供了一个类方法 getInstance
,以获得此类型的一个通用的对象。Calendar
的 getInstance
方法返回一个 Calendar
对象,其日历字段已由当前日期和时间初始化:
Calendar rightNow = Calendar.getInstance();
日历字段:
YEAR 这是哪年
MONTH 这是月(从0开始)
WEEK_OF_YEAR 今年的第几星期
WEEK_OF_MONTH 这个月的第几星期(从一开始)
DATE 今天几号
DAY_OF_MONTH 这个月的第几天
DAY_OF_YEAR 这一年的第几天
DAY_OF_WEEK 这周周几(从星期天开始计算,从1计算)
DAY_OF_WEEK_IN_MONTH 第几周(从第一天开始算一周)
AM_PM 上午还是下午 0为上午,1为下午
HOUR 12小时制几点
HOUR_OF_DAY 24小时制几点
MINUTE 多少分
SECOND 多少秒
MILLISECOND 多少毫秒
ZONE_OFFSET 时区
通过一个例子来看java.util.Calendar的使用:
public static void main(String[] args) throws SQLException{
//通过格式化输出日期
java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//取得年月日、小时分钟秒
Calendar cal = Calendar.getInstance();
System.out.println("年:"+cal.get(Calendar.YEAR));
System.out.println("月:"+cal.get(Calendar.MONTH)); // 0 - 11;java月份是从0-11,月份设置时要减1.
System.out.println("日:"+cal.get(Calendar.DATE));
System.out.println("时:"+cal.get(Calendar.HOUR_OF_DAY));
System.out.println("分:"+cal.get(Calendar.MINUTE));
System.out.println("秒:"+cal.get(Calendar.SECOND));
//取当前日期的前一天
Calendar cal1 = Calendar.getInstance();
cal1.add(Calendar.DAY_OF_MONTH, -1);
System.out.println("当前日期的前一天:"+format.format(cal1.getTime()));
//取当前日期的后一天
Calendar cal2 = Calendar.getInstance();
cal2.add(Calendar.DAY_OF_MONTH, +1);
System.out.println("当前日期的后一天:"+format.format(cal2.getTime()));
//判断当前月份的最大天数
Calendar cal3 = Calendar.getInstance();
int day=cal3.getActualMaximum(Calendar.DAY_OF_MONTH);
System.out.println("当前月份的最大天数:"+day);
//5小时前的时间
Calendar Cal4 = Calendar.getInstance();
Cal4.add(Calendar.HOUR_OF_DAY,-5);
System.out.println("5小时前的时间:"+format.format(Cal4.getTime()));
//加12个月
cal.set(Calendar.MONTH, 12);
//前一天
cal.set(Calendar.DATE, -1);
//根据今天获取星期一和星期天
System.out.println("今天 :"+format.format(new Date()));
Calendar c=Calendar.getInstance();
c.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
System.out.println("星期一:"+format.format(c.getTime()));
c.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY);
System.out.println("星期六:"+format.format(c.getTime()));
- }
Calendar 与 Date 的转换非常简单:
Calendar calendar = Calendar.getInstance();
// 从一个 Calendar 对象中获取 Date 对象
Date date = calendar.getTime();
// 将 Date 对象反应到一个 Calendar 对象中,
// Calendar/GregorianCalendar 没有构造函数可以接受 Date 对象
// 所以我们必需先获得一个实例,然后设置 Date 对象
calendar.setTime(date);
2、java.text.SimpleDateFormat
SimpleDateFormat主要有两个功能:时间日期的格式化和字符串解析为时间,全部时间类型都可以被SimpleDateFormat格式化format()为字符串对象,如下例:
String pattern_ymd_hms = "yyyy-MM-dd HH:mm:ss"; // pattern_ymdtime
DateFormat format = new SimpleDateFormat(pattern_ymd_hms);
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 sqlTimestamp = new java.sql.Timestamp(utildate.getTime());
System.out.println("utildate格式转换:"+format.format(utildate));
System.out.println("sqlDate格式转换:"+format.format(sqlDate));
System.out.println("sqlTime格式转换:"+format.format(sqlTime));
System.out.println("sqlTimestamp格式转换:"+format.format(sqlTimestamp));
utildate格式转换:2017-06-26 11:00:01
sqlDate格式转换:2017-06-26 11:00:01
sqlTime格式转换:2017-06-26 11:00:01
sqlTimestamp格式转换:2017-06-26 11:00:01
将字符串解析为时间类型:
SimpleDateFormat format = new SimpleDateFormat(pattern_ymd_hms);
try {
format.parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
3、Date and Time Patterns
在上面的例子中,我们看到“yyyy-MM-dd HH:mm:ss”这样的时间格式,它们每个字母都代表什么意思呢。下面是我查询JDK的API文档获得的内容(只列举了常用的一些):
其中需要注意的有:
1、HH和hh:HH代表的是24小时制;hh代表的是12小时制。
2、yyyy和YYYY的区别,其中大写的Y,代表的是week year,其意思是当天所在的周属于的年份,一周从周日开始,周六结束,只要本周跨年,那么这周就算入下一年,例如2010.12.26,日历长成这样
12.26所在的周的最后一天是2011.1.1,这天属于2011,所以2010.12.26的Week year就是2011,用YYYY做格式化,就会得到2011.12.26。
参考: