UTC dateTimeをDBに保存する必要があります。
特定のタイムゾーンで指定されたdateTimeをUTCに変換しました。そのため、以下のコードに従いました。
入力日時は「20121225 10:00:00 Z」タイムゾーンは「アジア/カルカッタ」です
私のサーバー/ DB(Oracle)は同じタイムゾーン(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(Oracle)は、UTCではなく同じdateTime: "20121225 10:00:00
を保存しています。
以下のSQLから確認しました。
select to_char(sched_start_time, 'yyyy/mm/dd hh24:mi:ss') from myTable
DBサーバーも同じタイムゾーン「Asia/Calcutta」で実行されています
それは私に以下の外観を与えます
Date.getTime()
はUTCではありませんもう1つの質問:
timeStamp.toString()
は、Java.util.date
のようにローカルタイムゾーンで印刷しますか? UTCではありませんか?
setTimestamp(int parameterIndex, Timestamp x)
には明示的に指定されていませんが、ドライバーは setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
javadoc によって確立された規則に従う必要があります。
指定された
Calendar
オブジェクトを使用して、指定されたパラメーターを指定されたJava.sql.Timestamp
値に設定します。ドライバーはCalendar
オブジェクトを使用してSQLTIMESTAMP
値を作成し、それをドライバーがデータベースに送信します。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」としてタイムスタンプを取得します。
別のタイムゾーンに保存する場合は、必要なタイムゾーンのCalendarインスタンスでsetTimestamp(int parameterIndex, Timestamp x, Calendar cal)
を使用する必要があります。値を取得するときに、同じタイムゾーンで同等のゲッターも使用することを確認してください(データベースでタイムゾーン情報なしでTIMESTAMP
を使用する場合)。
したがって、実際のGMTタイムゾーンを保存する場合は、次を使用する必要があります。
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
stmt.setTimestamp(11, tsSchedStartTime, cal);
JDBC 4.2では、準拠ドライバは、Java.time.LocalDateTime
を介してTIMESTAMP
(およびTIME
)に対してJava.time.LocalTime
(およびget/set/updateObject
)をサポートする必要があります。 Java.time.Local*
クラスにはタイムゾーンがないため、変換を適用する必要はありません(ただし、コードが特定のタイムゾーンを想定している場合、新しい問題が発生する可能性があります)。
正しい答えは、Java.sql.Timestampはタイムゾーン固有ではないはずだと思います。タイムスタンプは、Java.util.Dateと個別のナノ秒値の複合です。このクラスにはタイムゾーン情報はありません。したがって、Dateと同様に、このクラスは、1970年1月1日00:00:00 GMT + nanosからのミリ秒数を単に保持します。
PreparedStatement.setTimestamp(int parameterIndex、Timestamp x、Calendar cal)では、ドライバーはデフォルトのタイムゾーンを変更するためにカレンダーを使用します。ただし、タイムスタンプはGMTでミリ秒を保持します。
APIは、JDBCドライバーがカレンダーをどの程度正確に使用するかについて明確ではありません。プロバイダーは、それを解釈する方法について自由に感じているようです。前回MySQL 5.5カレンダーで作業したとき、ドライバーはPreparedStatement.setTimestampとResultSet.getTimestampの両方でカレンダーを単に無視しました。
それはあなたのドライバーに固有のものです。 Javaプログラムでパラメーターを指定して、使用するタイムゾーンを指定する必要があります。
Java -Duser.timezone="America/New_York" GetCurrentDateTimeZone
さらにこれ:
to_char(new_time(sched_start_time, 'CURRENT_TIMEZONE', 'NEW_TIMEZONE'), 'MM/DD/YY HH:MI AM')
変換を適切に処理することにも価値があります。 here から取得
Mysqlには、制限があります。 driver Mysql doc には、次のものがあります。
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 = 19/04/2016-21:10:56 GMT
2番目のメソッドは以下を返します:1461100256000 = 19/04/2016-21:10:56 GMT
3番目のメソッドは以下を返します:1461085856000 = 19/04/2016-17:10:56 GMT
Oracleの代わりに、同じ呼び出しを使用すると、次のようになります。
最初のメソッドは以下を返します:1461093056000 = 19/04/2016-19:10:56 GMT
2番目のメソッドは以下を返します:1461100256000 = 19/04/2016-21:10:56 GMT
3番目のメソッドは以下を返します:1461085856000 = 19/04/2016-17:10:56 GMT
NB:Oracleのパラメーターを指定する必要はありません。