java.sql.Timestamp 시간대는 특정입니까?
UTC dateTime을 DB에 저장해야합니다.
특정 시간대에 지정된 dateTime을 UTC로 변환했습니다. 이를 위해 아래 코드를 따랐습니다.
내 입력 dateTime은 "20121225 10:00:00 Z"입니다. 시간대는 "Asia / Calcutta"입니다.
내 서버 / DB (oracle)는 동일한 시간대 (IST) "Asia / Calcutta"에서 실행 중입니다.
이 특정 시간대의 Date 객체를 가져옵니다.
String date = "20121225 10:00:00 Z";
String timeZoneId = "Asia/Calcutta";
TimeZone timeZone = TimeZone.getTimeZone(timeZoneId);
DateFormat dateFormatLocal = new SimpleDateFormat("yyyyMMdd HH:mm:ss z");
//This date object is given time and given timezone
java.util.Date parsedDate = dateFormatLocal.parse(date + " "
+ timeZone.getDisplayName(false, TimeZone.SHORT));
if (timeZone.inDaylightTime(parsedDate)) {
// We need to re-parse because we don't know if the date
// is DST until it is parsed...
parsedDate = dateFormatLocal.parse(date + " "
+ timeZone.getDisplayName(true, TimeZone.SHORT));
}
//assigning to the java.sql.TimeStamp instace variable
obj.setTsSchedStartTime(new java.sql.Timestamp(parsedDate.getTime()));
DB에 저장
if (tsSchedStartTime != null) {
stmt.setTimestamp(11, tsSchedStartTime);
} else {
stmt.setNull(11, java.sql.Types.DATE);
}
산출
DB (oracle)는 dateTime: "20121225 10:00:00
UTC가 아닌 동일한 내용을 저장했습니다 .
아래 SQL에서 확인했습니다.
select to_char(sched_start_time, 'yyyy/mm/dd hh24:mi:ss') from myTable
내 DB 서버도 동일한 시간대 "Asia / Calcutta"에서 실행됩니다.
다음과 같은 모습을 보여줍니다.
Date.getTime()
UTC가 아닙니다.- 또는 Timestamp는 DB에 저장하는 동안 시간대에 영향을 미칩니다. 여기서 뭘 잘못하고 있습니까?
질문 하나 더 :
윌 timeStamp.toString()
같은 지역의 시간대로 인쇄 java.util.date
합니까? UTC가 아닌가요?
setTimestamp(int parameterIndex, Timestamp x)
드라이버에 대해 명시 적으로 지정되지는 않았지만 setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
javadoc에서 설정 한 규칙을 따라야합니다 .
java.sql.Timestamp
지정된Calendar
개체를 사용하여 지정된 매개 변수를 지정된 값으로 설정 합니다. 드라이버는Calendar
개체를 사용하여 SQLTIMESTAMP
값 을 생성 한 다음 드라이버가 데이터베이스로 보냅니다. A를Calendar
사용자 정의 시간대를 계정에 객체, 드라이버는 타임 스탬프 복용을 계산할 수 있습니다.Calendar
개체를 지정 하지 않으면 드라이버는 애플리케이션을 실행하는 가상 머신의 기본 시간대를 사용합니다.
setTimestamp(int parameterIndex, Timestamp x)
JDBC 드라이버로 호출 할 때 가상 머신의 시간대를 사용하여 해당 시간대의 시간 소인 날짜 및 시간을 계산합니다. 이 날짜와 시간은 데이터베이스에 저장되며, 데이터베이스 열에 시간대 정보가 저장되지 않으면 해당 영역에 대한 모든 정보가 손실됩니다 (즉, 데이터베이스를 사용하는 응용 프로그램이 동일한 시간대를 일관되게 사용하거나 시간대를 식별하기위한 다른 체계를 마련합니다 (예 : 별도의 열에 저장).
예 : 현지 시간대는 GMT + 2입니다. "2012-12-25 10:00:00 UTC"를 저장합니다. 데이터베이스에 저장된 실제 값은 "2012-12-25 12:00:00"입니다. 다시 검색합니다. "2012-12-25 10:00:00 UTC"로 다시 가져 오지만을 사용하여 검색하는 경우에만 해당 getTimestamp(..)
되지만 다른 응용 프로그램이 GMT + 0 시간대의 데이터베이스에 액세스하면 타임 스탬프를 "2012-12-25 12:00:00 UTC"로 검색합니다.
다른 시간대에 저장 setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
하려면 필요한 시간대의 캘린더 인스턴스와 함께 를 사용해야합니다 . 값을 검색 할 때 동일한 시간대의 동등한 getter도 사용하는지 확인하십시오 ( TIMESTAMP
데이터베이스에서 시간대 정보없이 를 사용하는 경우 ).
따라서 실제 GMT 시간대를 저장한다고 가정하면 다음을 사용해야합니다.
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
stmt.setTimestamp(11, tsSchedStartTime, cal);
With JDBC 4.2 a compliant driver should support java.time.LocalDateTime
(and java.time.LocalTime
) for TIMESTAMP
(and TIME
) through get/set/updateObject
. The java.time.Local*
classes are without time zones, so no conversion needs to be applied (although that might open a new set of problems if your code did assume a specific time zone).
I think the correct answer should be java.sql.Timestamp is NOT timezone specific. Timestamp is a composite of java.util.Date and a separate nanoseconds value. There is no timezone information in this class. Thus just as Date this class simply holds the number of milliseconds since January 1, 1970, 00:00:00 GMT + nanos.
In PreparedStatement.setTimestamp(int parameterIndex, Timestamp x, Calendar cal) Calendar is used by the driver to change the default timezone. But Timestamp still holds milliseconds in GMT.
API is unclear about how exactly JDBC driver is supposed to use Calendar. Providers seem to feel free about how to interpret it, e.g. last time I worked with MySQL 5.5 Calendar the driver simply ignored Calendar in both PreparedStatement.setTimestamp and ResultSet.getTimestamp.
It is specific from your driver. You need to supply a parameter in your Java program to tell it the time zone you want to use.
java -Duser.timezone="America/New_York" GetCurrentDateTimeZone
Further this:
to_char(new_time(sched_start_time, 'CURRENT_TIMEZONE', 'NEW_TIMEZONE'), 'MM/DD/YY HH:MI AM')
May also be of value in handling the conversion properly. Taken from here
For Mysql, we have a limitation. In the driver Mysql doc, we have :
The following are some known issues and limitations for MySQL Connector/J: When Connector/J retrieves timestamps for a daylight saving time (DST) switch day using the getTimeStamp() method on the result set, some of the returned values might be wrong. The errors can be avoided by using the following connection options when connecting to a database:
useTimezone=true
useLegacyDatetimeCode=false
serverTimezone=UTC
So, when we do not use this parameters and we call setTimestamp or getTimestamp
with calendar or without calendar, we have the timestamp in the jvm timezone.
Example :
The jvm timezone is GMT+2. In the database, we have a timestamp : 1461100256 = 19/04/16 21:10:56,000000000 GMT
Properties props = new Properties();
props.setProperty("user", "root");
props.setProperty("password", "");
props.setProperty("useTimezone", "true");
props.setProperty("useLegacyDatetimeCode", "false");
props.setProperty("serverTimezone", "UTC");
Connection con = DriverManager.getConnection(conString, props);
......
Calendar nowGMT = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Calendar nowGMTPlus4 = Calendar.getInstance(TimeZone.getTimeZone("GMT+4"));
......
rs.getTimestamp("timestampColumn");//Oracle driver convert date to jvm timezone and Mysql convert date to GMT (specified in the parameter)
rs.getTimestamp("timestampColumn", nowGMT);//convert date to GMT
rs.getTimestamp("timestampColumn", nowGMTPlus4);//convert date to GMT+4 timezone
The first method returns : 1461100256000 = 19/04/2016 - 21:10:56 GMT
The second method returns : 1461100256000 = 19/04/2016 - 21:10:56 GMT
The third method returns : 1461085856000 = 19/04/2016 - 17:10:56 GMT
Instead of Oracle, when we use the same calls, we have :
The first method returns : 1461093056000 = 19/04/2016 - 19:10:56 GMT
The second method returns : 1461100256000 = 19/04/2016 - 21:10:56 GMT
The third method returns : 1461085856000 = 19/04/2016 - 17:10:56 GMT
NB : It is not necessary to specify the parameters for Oracle.
참고URL : https://stackoverflow.com/questions/14070572/is-java-sql-timestamp-timezone-specific
'Program Tip' 카테고리의 다른 글
Nginx를 사용한 WSGI 대 uWSGi (0) | 2020.10.21 |
---|---|
Rails .where 대 .find (0) | 2020.10.21 |
for 루프를 사용하고 값을 전달하는 addEventListener (0) | 2020.10.21 |
iOS / OSX 프레임 워크 생성 : 다른 개발자에게 배포하기 전에 코드 서명이 필요합니까? (0) | 2020.10.21 |
Android SDK 버전을 검색하는 방법은 무엇입니까? (0) | 2020.10.21 |