Date, Calendar, Date国际化

1.Date.getTime() 和 Calendar.getTimeInMillis() 返回自 1970 年 1 月 1 日 00:00:00 GMT+0 以来此 Date 对象表示的毫秒数。

证明

package com.siyuan.test.jdk;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

public class TimeTest {

	public static void main(String[] args) throws ParseException {
		SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Calendar calendar = Calendar.getInstance();
		String timeStr = "1970-01-01 00:00:00";
		Date time = dateFmt.parse(timeStr);
		System.out.println(time.getTime());
	    calendar.setTime(time);
	    System.out.println(calendar.getTimeInMillis());
        System.out.println(TimeZone.getDefault());
	}

}

输出结果

-28800000
-28800000
sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null]

 -28800000 = 8 * 3600 * 1000

Asia/Shanghai 位于 GMT+0800

2.TimeZone对DateFormat的影响

package com.siyuan.test.jdk;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

public class DateFormatTest {

	public static void main(String[] args) {
		SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		Calendar calendar = Calendar.getInstance();
		System.out.println(dateFmt.format(calendar.getTime()));
		System.out.println(dateFmt.getTimeZone());
		System.out.println(TimeZone.getDefault());
		System.out.println("======================================================");
		dateFmt.setTimeZone(TimeZone.getTimeZone("GMT+00"));
		System.out.println(dateFmt.format(calendar.getTime()));
	}
	
}

 输出结果

2014-10-20 22:34:44
sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null]
sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null]
======================================================
2014-10-20 14:34:44

3.MySQL中的DateTime数据类型 

1)建表

CREATE TABLE `t_date_i18n` (
  `FID` int(11) NOT NULL AUTO_INCREMENT,
  `FDate` datetime DEFAULT NULL,
  `FTimeStamp` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`FID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2)JDBC操作

--存储

package com.siyuan.test.jdk;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class DBDateTest {
	
	public static String DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";

	public static String USER_NAME = "root";

	public static String PASSWORD = "123456";

	public static String URL = "jdbc:mysql://localhost:3306/study";

	public static Connection getConnection() throws ClassNotFoundException, SQLException {
		Class.forName(DRIVER_CLASS_NAME);
		return DriverManager.getConnection(URL, USER_NAME, PASSWORD);
	}
	
	public static final String SQL_SAVE = "INSERT INTO t_date_i18n(FDate, FTimeStamp) values(?, ?)";
	
	/**
	 * 使用setDate方法存储
	 */
	public void save(Date date) {
		Connection conn = null;
		PreparedStatement pstat = null;
		try {
			conn = DBDateTest.getConnection();
			conn.setAutoCommit(false);
			pstat = conn.prepareStatement(SQL_SAVE);
			java.sql.Date dateSaved = new java.sql.Date(date.getTime());
			pstat.setDate(1, dateSaved);
			pstat.setDate(2, dateSaved);
			pstat.executeUpdate();
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				pstat.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * 使用setTimestamp方法存储
	 */
	public void save_2(Date date) {
		Connection conn = null;
		PreparedStatement pstat = null;
		try {
			conn = DBDateTest.getConnection();
			conn.setAutoCommit(false);
			pstat = conn.prepareStatement(SQL_SAVE);
			Timestamp timestampSaved = new Timestamp(date.getTime());
			pstat.setTimestamp(1, timestampSaved);
			pstat.setTimestamp(2, timestampSaved);
			pstat.executeUpdate();
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				pstat.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void main(String[] args) throws ParseException {
		DBDateTest test = new DBDateTest();
		DateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String dateStr = "2014-10-25 00:00:00";
		Date date1 = dateFmt.parse(dateStr);
		test.save(date1);
		dateFmt.setTimeZone(TimeZone.getTimeZone("GMT+00"));
		Date date2 = dateFmt.parse(dateStr);
		test.save_2(date2);
		
		TimeZone.setDefault(TimeZone.getTimeZone("GMT+02"));
		DateFormat dateFmt2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		date1 = dateFmt2.parse(dateStr);
		test.save(date1);
		dateFmt2.setTimeZone(TimeZone.getTimeZone("GMT+00"));
		date2 = dateFmt2.parse(dateStr);
		test.save_2(date2);
	}

}

结果:

Date, Calendar, Date国际化
java.sql.Date

为了与 SQL DATE 的定义一致,由 java.sql.Date 实例包装的毫秒值必须通过将小时、分钟、秒和毫秒设置为与该实例相关的特定时区中的零来“规范化”。 

java.sql.Timestamp

将时间转化为JDK默认TimeZone对应的时间进行存储。

存储时均和数据库的时区无关。

--读取

package com.siyuan.test.jdk;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class DBDateTest {
	
	public static String DRIVER_CLASS_NAME = "com.mysql.jdbc.Driver";

	public static String USER_NAME = "root";

	public static String PASSWORD = "123456";

	public static String URL = "jdbc:mysql://localhost:3306/study";

	public static Connection getConnection() throws ClassNotFoundException, SQLException {
		Class.forName(DRIVER_CLASS_NAME);
		return DriverManager.getConnection(URL, USER_NAME, PASSWORD);
	}
	
	public static final String SQL_GET = "SELECT FDate, FTimeStamp FROM t_date_i18n WHERE FID = ?";
	
	/**
	 * 使用setDate方法存储
	 */
	public void get(int id) {
		Connection conn = null;
		PreparedStatement pstat = null;
		try {
			conn = DBDateTest.getConnection();
			conn.setAutoCommit(false);
			pstat = conn.prepareStatement(SQL_GET);
			pstat.setInt(1, id);
			ResultSet rs = pstat.executeQuery();
			if (rs.next()) {
				System.out.println(format(rs.getDate(1)));
				System.out.println(format(rs.getTimestamp(2)));
			}
			conn.commit();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				pstat.close();
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static String format(Date date) {
		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
	}
	
	public static void main(String[] args) throws ParseException {
		DBDateTest test = new DBDateTest();
		test.get(1);
		
		TimeZone.setDefault(TimeZone.getTimeZone("GMT+02"));
		test.get(1);
	}

}

结果

2014-10-25 00:00:00
2014-10-25 00:00:00
2014-10-25 00:00:00
2014-10-25 00:00:00

结论:

读取时保持时间一致,不管当前JDK的默认TimeZone是多少

3)MyBatis操作

--存储

package com.siyuan.test.mybatis.dao;

import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import com.siyuan.test.mybatis.entity.DateI18N;

public class DateI18NTest {

	public static void main(String[] args) throws IOException, ParseException {
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
		
		SqlSession session2 = sqlSessionFactory.openSession();
		try {
			DateFormat dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			String dateStr = "2014-10-25 00:00:00";
			DateI18N dateI18N = new DateI18N();
			DateI18NDAO dateI18NDAO = session2.getMapper(DateI18NDAO.class);
			
			Date date1 = dateFmt.parse(dateStr);
			dateI18N.setDate(date1);
			dateI18NDAO.insert(dateI18N);
			
			dateFmt.setTimeZone(TimeZone.getTimeZone("GMT+00"));
			Date date2 = dateFmt.parse(dateStr);
			dateI18N.setDate(date2);
			dateI18NDAO.insert(dateI18N);
			
			TimeZone.setDefault(TimeZone.getTimeZone("GMT+02"));
			dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			date1 = dateFmt.parse(dateStr);
			dateI18N.setDate(date1);
			dateI18NDAO.insert(dateI18N);
			
			dateFmt.setTimeZone(TimeZone.getTimeZone("GMT+00"));
			date2 = dateFmt.parse(dateStr);
			dateI18N.setDate(date2);
			dateI18NDAO.insert(dateI18N);
			
			session2.commit();
		} finally {
			session2.close();
		}
		
	}

}

 DateI18N.java

package com.siyuan.test.mybatis.entity;

import java.util.Date;

public class DateI18N {
	
	private Date date;
	
	public DateI18N() {
		
	}

	public Date getDate() {
		return date;
	}

	public void setDate(Date date) {
		this.date = date;
	}
	
}

DateI18NDAO.java

package com.siyuan.test.mybatis.dao;

import com.siyuan.test.mybatis.entity.DateI18N;

public interface DateI18NDAO {
	
	void insert(DateI18N dateI18N);
	
}

 DateI18NDAO.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.siyuan.test.mybatis.dao.DateI18NDAO">
    
    <insert id="insert" parameterType="DateI18N">
        INSERT INTO t_date_i18n (FDate)
        VALUES
            (#{date})
    </insert>
    
</mapper>

 结果:

Date, Calendar, Date国际化

MyBatis的DateTypeHandler是采用Timestamp来处理Date对象的

4.国际化Date的方案

1)在对应的表里面新增一个字段,保存TimeZone

2)保存时统一为某一固定的TimeZone,读取时根据所需TimeZone进行转化

你可能感兴趣的:(calendar)