codememo

is java.sql.타임스탬프 시간대를 지정하시겠습니까?

tipmemo 2023. 9. 25. 22:47
반응형

is java.sql.타임스탬프 시간대를 지정하시겠습니까?

UTC dateTime을 DB에 저장해야 합니다.
특정 시간대에 주어진 dateTime을 UTC로 변환하여 아래의 코드를 따릅니다.
제 은 "은 "20121225 10:00 Z"는 아타"다입니다.
가 버/DB클)대(IST) 아타".

이 특정 시간대의 날짜 개체 가져오기

        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(를) 을()와 하였습니다.dateTime: "20121225 10:00:00UTC에는 없습니다.

아래 sql에서 확인하였습니다.

     select to_char(sched_start_time, 'yyyy/mm/dd hh24:mi:ss') from myTable

같은 시간대 "아시아/캘커타"에서도 실행되는 나의 DB 서버

그것은 나에게 다음과 같은 외관을 제공합니다.

  1. Date.getTime()는 UTC다에 .
  2. 또는 타임스탬프가 DB에 저장하는 동안 시간대에 영향을 미칩니다. 여기서 제가 무엇을 잘못하고 있습니까?

한가지 더 묻겠습니다.

할 것이다timeStamp.toString()다처럼 할 수 있습니다.java.util.date요? UTC요?

}에 setTimestamp(int parameterIndex, Timestamp x)드라이버들은 javadoc에 의해 정해진 규칙을 따라야 합니다.

된 로 합니다.java.sql.Timestamp된 값을 사용하여합니다.Calendar물건.운전자는 다음을 사용합니다.CalendarTIMESTAMPdatabase.value로 합니다. 드라이버가 데이터베이스로 전송합니다. 포함Calendar, 는 사용자 할 수 object,다.안되면Calendar개체를 지정하고, 드라이버는 애플리케이션을 실행하는 가상 시스템의 기본 시간대인 기본 시간대를 사용합니다.

는.setTimestamp(int parameterIndex, Timestamp x)JDBC 드라이버는 가상 시스템의 시간대를 사용하여 해당 시간대의 타임스탬프 날짜와 시간을 계산합니다.이 날짜 및 시간은 데이터베이스에 저장된 시간이며, 데이터베이스 열에 시간대 정보가 저장되지 않으면 시간대에 대한 정보가 손실됩니다(즉, 동일한 시간대를 일관되게 사용하거나 다른 방식으로 시간대를 구분하는 것이 데이터베이스를 사용하는 응용프로그램에 달려 있음).

예를 들어, 현지 시간대는 GMT+2입니다."합니다를 합니다.데이터베이스에 저장된 실제 값은 "2012-12-25 12:00:00"입니다.단, "2012-12-25 10:00 UTC"면합니다,당)를 사용하여 에만 해당).getTimestamp(..) 다른 "로 됩니다.),이 GMT+0 시간대에 "2012-12-25 12:00 UTC" 로됩니다가 가됩니다.

하시려면 setTimestamp(int parameterIndex, Timestamp x, Calendar cal)필요한 표준 시간대에 Calendar 인스턴스를 포함합니다.때오우)를).TIMESTAMP(데이터베이스에 시간대 정보가 없는 경우).

따라서 실제 GMT 시간대를 저장하려면 다음을 사용해야 합니다.

Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
stmt.setTimestamp(11, tsSchedStartTime, cal);

준수 가 JDBC 4.2를 해야 함java.time.LocalDateTime(그리고java.time.LocalTime)에 대하여TIMESTAMP(그리고TIME부터 )까지get/set/updateObject.java.time.Local*클래스는 시간대가 없으므로 변환을 적용할 필요가 없습니다(코드가 특정 시간대를 가정한 경우 새로운 문제 집합이 열릴 수 있음).

즉,

  • 을 바꾸다getDate(..)와 함께getObject(.., LocalDate.class)
  • 을 바꾸다setDate(.., dateValue)와 함께setObject(.., localDateValue)
  • 을 바꾸다getTime(..)와 함께getObject(.., LocalTime.class)
  • 을 바꾸다setTime(.., timeValue)와 함께setObject(.., localTimeValue)
  • 을 바꾸다getTimestamp(..)와 함께getObject(.., LocalDateTime.class)
  • 을 바꾸다setTimestamp(.., timestampValue)와 함께setObject(.., localDateTimeValue)

정답은 java.sql이 되어야 한다고 생각합니다.타임스탬프는 시간대별이 아닙니다.타임스탬프는 java.util의 합성어입니다.날짜 및 별도의 나노초 값입니다.이 클래스에는 시간대 정보가 없습니다.따라서 이 클래스는 1970년 1월 1일 00:00:00 GMT + nanos 이후의 밀리초 수를 유지합니다.

준비 상태.setTimestamp(int 파라미터)에서인덱스, 타임스탬프 x, Calendar cal) Calendar는 드라이버가 기본 시간대를 변경하는 데 사용됩니다.그러나 타임스탬프는 GMT에서 여전히 밀리초를 유지합니다.

JDBC 드라이버가 정확히 캘린더를 어떻게 사용해야 하는지 API가 불분명합니다.예를 들어, 내가 MySQL 5.5 캘린더로 작업했을 때 드라이버가 PreparedStatement.setTimestamp와 ResultSet.getTimestamp에서 캘린더를 단순히 무시한 것과 같이 프로바이더는 그것을 어떻게 해석할지에 대해 자유롭게 생각하는 것 같습니다.

그 입니다.java.sql.Timestamp엉망인 상태이므로 피해야 합니다. 사용합니다.java.time.LocalDateTime대신.

그런데 왜 이렇게 엉망진창일까요? 더 프롬 더java.sql.Timestamp,, ajava.sql.Timestamp지"입니다 입니다.java.util.Date이를 통해 JDBC API 가 이 값SQL TIMESTAMP 값으로 식별할 수 있습니다" From thejava.util.Date"Date등급은 조정된 보편적 시간(UTC) 을 반영하기 위한 것입니다." ZONE 없는 합니다.ISO SQL 사양에서 타임스탬프 WITH TIME ZONE "시간대가 없는 날짜 시간인 데이터 유형입니다."타임스탬프는 타임스탬프가 없는 타임스탬프의 짧은 이름입니다. 그래서 ajava.sql.Timestamp"반영" UTC인 반면 SQL TIMESTAMP는 "시간대 없음"입니다.

.java.sql.TimestampUTC를 반영합니다. 변환을 적용하는 메서드입니다.이것은 끊임없는 혼란을 야기합니다.SQL 관점에서 볼 때, 타임스탬프에 변환할 시간대가 없으므로 SQL TIMEPSP 값을 다른 시간대로 변환하는 것은 의미가 없습니다.42를 화씨로 바꾼다는 것은 무슨 뜻입니까?42에는 온도 단위가 없기 때문에 아무 의미가 없습니다.그냥 숫자에 불과합니다.마찬가지로 2020-07-22T10:30:00은 시간대에 없으므로 2020-07-22T10:38:00의 타임스탬프를 아메리카/로스앤젤레스로 변환할 수 없습니다.그것은 UTC나 GMT 그 밖의 어떤 것에도 없습니다.데이트 시간이 얼마 남지 않았습니다.

java.time.LocalDateTime데이트 시간도 짧습니다.SQL TIMESTAMP와 같은 시간대가 없습니다. 어떤 방법도 동작을 예측하고 이해하기 훨씬 더 쉽게 만드는 어떤 종류의 시간대 변환도 적용하지 않습니다.사용하지 마십시오.java.sql.Timestamp.사용하다java.time.LocalDateTime.

LocalDateTime ldt = rs.getObject(col, LocalDateTime.class);
ps.setObject(param, ldt, JDBCType.TIMESTAMP);

아래 방법을 사용하여 원하는 영역/영역 ID별 데이터베이스에 타임스탬프를 저장할 수 있습니다.

ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("Asia/Calcutta")) ;
Timestamp timestamp = Timestamp.valueOf(zdt.toLocalDateTime());

사람들이 흔히 하는 실수는 사용하는 것입니다.LocaleDateTime나중에 변환을 시도하더라도 영역에 지정된 모든 정보를 폐기하는 해당 순간의 타임스탬프를 가져옵니다.그것은 존을 이해하지 못합니다.

부디 참고하세요Timestamp의 ㅇjava.sql.Timestamp.

Mysql의 경우, 우리는 한계가 있습니다.드라이버 Mysql 문서에는 다음과 같은 내용이 있습니다.

다음은 MySQL Connector/J에 대해 알려진 몇 가지 문제 및 제한 사항입니다. Connector/J가 결과 집합에서 getTimeStamp() 메서드를 사용하여 DST(일광 절약 시간) 스위치 데이에 대한 타임스탬프를 검색할 때 반환된 값 중 일부가 잘못되었을 수 있습니다.데이터베이스에 연결할 때 다음 연결 옵션을 사용하여 오류를 방지할 수 있습니다.

useTimezone=true
useLegacyDatetimeCode=false
serverTimezone=UTC

이할 수 .setTimestamp or getTimestamp달력이 있든 없든 jvm 시간대에 타임스탬프가 있습니다.

예:

jvm 시간대는 GMT+2입니다.데이터베이스에는 타임스탬프가 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

첫번째 방법은 1461100256000 = 2016/04/19 - 21:10:56 GMT를 반환합니다.

두번째 방법은 1461100256000 = 2016/04/19 - 21:10:56 GMT를 반환합니다.

세번째 방법은 1461085856000 = 2016/04/19 - 17:10:56 GMT로 돌아옵니다.

Oracle 대신 동일한 호출을 사용할 경우 다음과 같은 이점이 있습니다.

첫번째 방법은 1461093056000 = 2016/04/19 - GMT 19:10:56

두번째 방법은 1461100256000 = 2016/04/19 - 21:10:56 GMT를 반환합니다.

세번째 방법은 1461085856000 = 2016/04/19 - 17:10:56 GMT로 돌아옵니다.

NB : Oracle에 대한 매개 변수를 지정할 필요는 없습니다.

그것은 당신의 운전기사에 의해 특정됩니다.사용할 시간대를 알려주기 위해서는 자바 프로그램에 파라미터를 입력해야 합니다.

java -Duser.timezone="America/New_York" GetCurrentDateTimeZone

추가 내용:

to_char(new_time(sched_start_time, 'CURRENT_TIMEZONE', 'NEW_TIMEZONE'), 'MM/DD/YY HH:MI AM')

또한 변환을 적절하게 처리하는 데에도 가치가 있을 수 있습니다.여기서 찍었습니다.

로컬 영역의 타임스탬프를 가져오는 것이 문제라면 다음을 사용할 수 있습니다.

Timestamp.from(Instant.now()).toLocalDateTime()

언급URL : https://stackoverflow.com/questions/43808611/jdbc-datetime-returns-wrong-datetime-value

반응형