95

アプリケーションからの Timestamp 値があります。ユーザーは、任意のローカル TimeZone にいることができます。

この日付は、指定された時間が常に GMT であると想定する WebService に使用されるため、ユーザーのパラメーターを (EST) から (GMT) に変換する必要があります。ここにキッカーがあります: ユーザーは自分の TZ に気づいていません。彼は WS に送信したい作成日を入力するので、必要なものは次のとおりです。

ユーザー入力: 5/1/2008 6:12 PM (EST)
WS へのパラメーターは次のようにする必要があります: 5/1/2008 6:12 PM (GMT)

TimeStamps はデフォルトで常に GMT であることがわかっていますが、パラメータを送信すると、TS (GMT であることが想定されている) からカレンダーを作成しても、ユーザーが GMT でない限り、時間は常にオフになります。私は何が欠けていますか?

Timestamp issuedDate = (Timestamp) getACPValue(inputs_, "issuedDate");
Calendar issueDate = convertTimestampToJavaCalendar(issuedDate);
...
private static java.util.Calendar convertTimestampToJavaCalendar(Timestamp ts_) {
  java.util.Calendar cal = java.util.Calendar.getInstance(
      GMT_TIMEZONE, EN_US_LOCALE);
  cal.setTimeInMillis(ts_.getTime());
  return cal;
}

前のコードでは、これが結果として得られるものです (読みやすいように短い形式)。

[2008 年 5 月 1 日午後 11 時 12 分]

4

9 に答える 9

62
public static Calendar convertToGmt(Calendar cal) {

    Date date = cal.getTime();
    TimeZone tz = cal.getTimeZone();

    log.debug("input calendar has date [" + date + "]");

    //Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT 
    long msFromEpochGmt = date.getTime();

    //gives you the current offset in ms from GMT at the current date
    int offsetFromUTC = tz.getOffset(msFromEpochGmt);
    log.debug("offset is " + offsetFromUTC);

    //create a new calendar in GMT timezone, set to this date and add the offset
    Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    gmtCal.setTime(date);
    gmtCal.add(Calendar.MILLISECOND, offsetFromUTC);

    log.debug("Created GMT cal with date [" + gmtCal.getTime() + "]");

    return gmtCal;
}

現在の時刻( "12:09:05 EDT" from Calendar.getInstance())を次のように渡した場合の出力は次のとおりです。

DEBUG-入力カレンダーに日付があります[ThuOct23 12:09:05 EDT2008]
DEBUG-オフセットは-14400000DEBUG-
日付付きのGMTcalを作成しました[ThuOct23 08:09:05 EDT 2008]

12:09:05GMTは8:09:05EDTです。

ここで紛らわしいのは、現在のタイムゾーンでをCalendar.getTime()返すことDateと、カレンダーのタイムゾーンを変更して基になる日付もロールする方法がないことです。Webサービスが使用するパラメーターのタイプによっては、エポックからのミリ秒単位でWSを処理したい場合があります。

于 2008-10-23T16:17:38.410 に答える
29

回答ありがとうございます。さらなる調査の後、私は正しい答えにたどり着きました。Skip Head が述べたように、アプリケーションから取得していた TimeStamped は、ユーザーの TimeZone に合わせて調整されていました。したがって、ユーザーが午後 6 時 12 分 (EST) と入力すると、午後 2 時 12 分 (GMT) になります。私が必要としていたのは、ユーザーが入力した時間が WebServer リクエストに送信した時間になるように、変換を元に戻す方法でした。これを達成した方法は次のとおりです。

// Get TimeZone of user
TimeZone currentTimeZone = sc_.getTimeZone();
Calendar currentDt = new GregorianCalendar(currentTimeZone, EN_US_LOCALE);
// Get the Offset from GMT taking DST into account
int gmtOffset = currentTimeZone.getOffset(
    currentDt.get(Calendar.ERA), 
    currentDt.get(Calendar.YEAR), 
    currentDt.get(Calendar.MONTH), 
    currentDt.get(Calendar.DAY_OF_MONTH), 
    currentDt.get(Calendar.DAY_OF_WEEK), 
    currentDt.get(Calendar.MILLISECOND));
// convert to hours
gmtOffset = gmtOffset / (60*60*1000);
System.out.println("Current User's TimeZone: " + currentTimeZone.getID());
System.out.println("Current Offset from GMT (in hrs):" + gmtOffset);
// Get TS from User Input
Timestamp issuedDate = (Timestamp) getACPValue(inputs_, "issuedDate");
System.out.println("TS from ACP: " + issuedDate);
// Set TS into Calendar
Calendar issueDate = convertTimestampToJavaCalendar(issuedDate);
// Adjust for GMT (note the offset negation)
issueDate.add(Calendar.HOUR_OF_DAY, -gmtOffset);
System.out.println("Calendar Date converted from TS using GMT and US_EN Locale: "
    + DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT)
    .format(issueDate.getTime()));

コードの出力は次のとおりです。

現在のユーザーのタイムゾーン: EST
GMT からの現在のオフセット (時間単位):-4 (通常は -5、DST が調整されている場合を除く)
ACP からの TS: 2008-05-01 14:12:00.0
GMT および US_EN ロケールを使用して TS から変換されたカレンダー日付: 2008 年 5 月 1 日午後 6 時 12 分 (GMT)

于 2008-10-23T18:03:18.260 に答える
20

日付はWebサービスに関連して使用されるとおっしゃっていますが、ある時点で文字列にシリアル化されると思います。

この場合は、DateFormatクラスのsetTimeZoneメソッドを確認する必要があります。これにより、タイムスタンプを印刷するときに使用されるタイムゾーンが決まります。

簡単な例:

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));

Calendar cal = Calendar.getInstance();
String timestamp = formatter.format(cal.getTime());
于 2009-02-02T12:41:36.283 に答える
12

Joda Timeで解決できます:

Date utcDate = new Date(timezoneFrom.convertLocalToUTC(date.getTime(), false));
Date localDate = new Date(timezoneTo.convertUTCToLocal(utcDate.getTime()));

Java 8:

LocalDateTime localDateTime = LocalDateTime.parse("2007-12-03T10:15:30");
ZonedDateTime fromDateTime = localDateTime.atZone(
    ZoneId.of("America/Toronto"));
ZonedDateTime toDateTime = fromDateTime.withZoneSameInstant(
    ZoneId.of("Canada/Newfoundland"));
于 2011-12-25T04:03:48.943 に答える
8

TimeStampが元のシステムのタイムゾーンに設定されているようです。

これは非推奨ですが、機能するはずです。

cal.setTimeInMillis(ts_.getTime() - ts_.getTimezoneOffset());

非推奨ではない方法は、

Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000)

ただし、そのシステムはどのタイムゾーンにあるかを認識しているため、クライアント側で実行する必要があります。

于 2008-10-23T16:01:23.013 に答える
6

DateオブジェクトとTimestampオブジェクトはタイムゾーンに依存しません。これらのオブジェクトは、エポックからの特定の秒数を表し、その瞬間を時間と日として特定の解釈にコミットすることはありません。タイムゾーンは、GregorianCalendar (このタスクには直接必要ありません) とSimpleDateFormatにのみ画像を入力します。これらは、別々のフィールドと Date (またはlong ) 値の間で変換するためにタイムゾーン オフセットを必要とします。

OPの問題は、彼の処理の開始時にあります。ユーザーは時間を入力しますが、これはあいまいであり、ローカルの非GMTタイムゾーンで解釈されます。この時点での値は"6:12 EST"です。これは"11.12 GMT"または他のタイムゾーンとして簡単に出力できますが、 "6.12 GMT"に変更されることはありません。

"06:12""HH:MM" (ローカル タイム ゾーンがデフォルト) として解析するSimpleDateFormatのデフォルトを UTC にする方法はありません。SimpleDateFormatは、それ自体の利点としては少しスマートすぎます。

ただし、SimpleDateFormatインスタンスが適切なタイム ゾーンを使用するように納得させるには、それを入力に明示的に指定する必要があります。受信した (そして適切に検証された) "06:12"に固定文字列を追加するだけで、 "06:12 GMT"を次のように解析できます。 "HH:MM z" .

GregorianCalendarフィールドを明示的に設定したり、タイムゾーンや夏時間のオフセットを取得して使用したりする必要はありません。

本当の問題は、ローカル タイムゾーンにデフォルト設定されている入力、UTC にデフォルト設定されている入力、明示的なタイムゾーン表示が実際に必要な入力を分離することです。

于 2012-02-06T11:28:47.217 に答える
4

過去に私のために働いたのは、ユーザーのタイムゾーンとGMTの間のオフセット(ミリ秒単位)を決定することでした。オフセットを取得したら、(変換の進行方向に応じて)単純に加算/減算して、いずれかのタイムゾーンで適切な時間を取得できます。私は通常、Calendarオブジェクトのミリ秒フィールドを設定することでこれを実現しますが、タイムスタンプオブジェクトに簡単に適用できると確信しています。オフセットを取得するために使用するコードは次のとおりです

int offset = TimeZone.getTimeZone(timezoneId).getRawOffset();

timezoneIdは、ユーザーのタイムゾーン(ESTなど)のIDです。

于 2008-10-23T15:59:25.107 に答える