質問
作成した以下のコードを計算時間の間にタイムスタンプきく二つの異なるフォーマット:
public class dummyTime {
public static void main(String[] args) {
try {
convertDuration("2008-01-01 01:00 pm - 01:56 pm");
convertDuration("2008-01-01 8:30 pm - 2008-01-02 09:30 am");
} catch (Exception e) {
e.printStackTrace();
}
}
private static String convertDuration(String time) throws Exception {
String ts[] = time.split(" - ");
SimpleDateFormat formatNew = new SimpleDateFormat("HH:mm");
Date beg, end;
String duration = null;
beg = getDateTime(ts[0]);
end = getDateTime(ts[1], beg);
duration = formatNew.format(end.getTime() - beg.getTime());
System.out.println(duration + " /// " + time + " /// " + beg + " /// "
+ end);
return duration;
}
private static Date getDateTime(String dateTime) throws ParseException {
DateFormat formatOldDateTime = new SimpleDateFormat(
"yyyy-MM-dd hh:mm aa");
DateFormat formatOldTimeOnly = new SimpleDateFormat("hh:mm aa");
Date date = null;
try {
date = formatOldDateTime.parse(dateTime);
} catch (ParseException e) {
date = formatOldTimeOnly.parse(dateTime);
}
return date;
}
private static Date getDateTime(String dateTime, Date orig)
throws ParseException {
Date end = getDateTime(dateTime);
if (end.getYear() == 70) {
end.setYear(orig.getYear());
end.setMonth(orig.getMonth());
end.setDate(orig.getDate());
}
return end;
}
}
の出力を生成するには:
01:56 /// 2008-01-01 01:00 pm - 01:56 pm /// Tue Jan 01 13:00:00 CET 2008 /// Tue Jan 01 13:56:00 CET 2008
14:00 /// 2008-01-01 8:30 pm - 2008-01-02 09:30 am /// Tue Jan 01 20:30:00 CET 2008 /// Wed Jan 02 09:30:00 CET 2008
私の質問:
- されている理由は何でしょうか結果は常に間違った (+1h)?
- 何より うるタイムスタンプな す。==70見られたもんじゃないの getDay&setDay機能 推奨されていません。
多くの感謝をしたいと考えて運転さんの数時間です。
解決
私のコンピュータことにより2時間がなかったので、GMT+2、しょでGMT+1.ご注意
formatNew.format(end.getTime() - beg.getTime());
受取日、すなわち扱いお56ることによって実現されてい1970-01-01-00:56:00GMT+1.この問題を修正するには、迅速に通formatNew.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
第2項目を確認することができれば形式yyyy-MM-ddに失敗しました(キャッチしてください。構文解析エラー)、このようにしているのをご存知ありません。
他のヒント
あなたは、時間と分のない数を一日の時間をフォーマットしています。あなたは冬のCETのタイムゾーン[中央ヨーロッパ時間]であるとして、それはUTC(「GMT」)から1時間異なります。
あなたはおそらくCalendar
の代わりにDate
使用することにしたいです。またはます。
簡単な答え:それは日付なしで一日の時間を表すフォーマット値へのSimpleDateFormatを使うことは不適切です。
。長い答え:Javaの時間の値が "エポック" からのミリ秒数です:真夜中、1970年1月1日、UTC
。SimpleDateFormatのは、あなたがそれを有効なタイムスタンプを与えていることを前提として、日付と時刻にローカライズされた変換を適用します。私はあなたのロケールが一時間オフGMT(ヨーロッパ大陸)であると思われる、あなたは一時間消灯している結果を見ている理由ですので。
あなたはタイムゾーンGMTを設定することによっててSimpleDateFormatをだますこともできますが、、あなたはおそらく、明示的な数学を使って継続時間を表示する方がいいでしょう。
int duration = 90;
System.out.printf("%02d:%02d", duration / 60, duration % 60);
第一に、例文字列と一致しない: 8:30 pm
がパディングゼロになります。させていただいておりますが、誤植、すべて 08:30 pm
.
望ましくない文字列形式
ちなみに、これらの入力文字列形式であることが望ましいと言えます。-がよりよい方法で行われている利用規 ISO8601 フォーマット-12時間時計AM/PMは十分な注意が必要です。の標準フォーマットの利用は24時間、時間0-23.
-標準表記の間隔は、一対の日付/時刻文字列スラッシュで分離された: 2008-01-01T13:00/2008-01-01T13:56
.
ご入力文字列にはもう一つの深刻な問題:示 オフセットから世界標準時間 またはタイムゾーンになります。なまでに相殺し(オフセット時間帯しなければなバックと一般24時間対応。この無視し異常などのサマータイムDST)による23 25時間ます。
がわかっている場合は、それを時間帯に受信文字列、そして第二引数を取得し、正しい結果です。
java.時間
この問題はなかなかです。その後、新しいパースペクティブsupplantedの面倒な古い日付-時間の授業(Date
, Calendar
, 等) 現代のjava.時間ます。を使用していまjava.時間の例のコードです。
例クラス
こちらは完全にクラスの処理にこれらの文字列としてお客様の質問です。A Duration
が生産されています。
package javatimestuff;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Locale;
/**
*
* @author Basil Bourque
*/
public class DurationProcessor {
static final int SHORT = 30;
static final int LONG = 41;
static final DateTimeFormatter FORMATTER_LOCALDATETIME = DateTimeFormatter.ofPattern ( "uuuu-MM-dd hh:mm a" );
static final DateTimeFormatter FORMATTER_LOCALTIME = DateTimeFormatter.ofPattern ( "hh:mm a" );
static public Duration process ( String input ) {
return DurationProcessor.process ( input , ZoneOffset.UTC );
}
static public Duration process ( String input , ZoneId zoneId ) {
Duration d = Duration.ZERO; // Or maybe null. To be generated by the bottom of this code.
if ( null == input ) {
// …
System.out.println ( "ERROR - Passed null argument." );
return d;
}
if ( input.length () == 0 ) {
// …
System.out.println ( "ERROR - Passed empty string as argument." );
return d;
}
String inputModified = input.toUpperCase ( Locale.ENGLISH ); // Change `am` `pm` to `AM` `PM` for parsing.
String[] parts = inputModified.split ( " - " );
String inputStart = parts[ 0 ]; // A date-time sting.
String inputStop = parts[ 1 ]; // Either a date-time string or a time-only string (assume the same date).
ZonedDateTime start = null; // To be generated in this block of code.
try {
LocalDateTime ldt = LocalDateTime.parse ( inputStart , DurationProcessor.FORMATTER_LOCALDATETIME );
start = ldt.atZone ( zoneId );
} catch ( DateTimeParseException e ) {
// …
System.out.println ( "ERROR - The start failed to parse. inputStart: " + inputStart );
return d;
}
ZonedDateTime stop = null; // To be generated in this block of code.
switch ( input.length () ) {
case DurationProcessor.SHORT: // Example: "2008-01-01 01:00 pm - 01:56 pm"
try {
LocalTime stopTime = LocalTime.parse ( inputStop , DurationProcessor.FORMATTER_LOCALTIME );
stop = ZonedDateTime.of ( start.toLocalDate () , stopTime , zoneId );
} catch ( DateTimeParseException e ) {
// …
System.out.println ( "ERROR - The stop time failed to parse." );
return d;
}
break;
case DurationProcessor.LONG: // "2008-01-01 8:30 pm - 2008-01-02 09:30 am"
try {
LocalDateTime ldt = LocalDateTime.parse ( inputStop , DurationProcessor.FORMATTER_LOCALDATETIME );
stop = ldt.atZone ( zoneId );
} catch ( DateTimeParseException e ) {
// …
System.out.println ( "ERROR - The stop date-time failed to parse." );
return d;
}
break;
default:
// …
System.out.println ( "ERROR - Input string is of unexpected length: " + input.length () );
break;
}
d = Duration.between ( start , stop );
return d;
}
public static void main ( String[] args ) {
// Run with out time zone (assumes UTC).
Duration dShort = DurationProcessor.process ( "2008-01-01 01:00 pm - 01:56 pm" );
System.out.println ( "dShort: " + dShort );
Duration dLong = DurationProcessor.process ( "2008-01-01 08:30 pm - 2008-01-02 09:30 am" );
System.out.println ( "dLong: " + dLong );
// Run with specified time zone.
ZoneId z = ZoneId.of ( "America/Montreal" );
Duration dShortZoned = DurationProcessor.process ( "2008-01-01 01:00 pm - 01:56 pm" , z );
System.out.println ( "dShortZoned: " + dShortZoned );
Duration dLongZoned = DurationProcessor.process ( "2008-01-01 08:30 pm - 2008-01-02 09:30 am" , z );
System.out.println ( "dLongZoned: " + dLongZoned );
}
}
注意 main
法によりクラスの例としました.
第一対の電話を指定せずにタイムゾーンになります。でUTC24時間対応日が使用されます。
Duration dShort = DurationProcessor.process ( "2008-01-01 01:00 pm - 01:56 pm" );
System.out.println ( "dShort: " + dShort );
Duration dLong = DurationProcessor.process ( "2008-01-01 08:30 pm - 2008-01-02 09:30 am" );
System.out.println ( "dLong: " + dLong );
別の対話の場である指定のタイムゾーンになります。
ZoneId z = ZoneId.of ( "America/Montreal" );
Duration dShortZoned = DurationProcessor.process ( "2008-01-01 01:00 pm - 01:56 pm" , z );
System.out.println ( "dShortZoned: " + dShortZoned );
Duration dLongZoned = DurationProcessor.process ( "2008-01-01 08:30 pm - 2008-01-02 09:30 am" , z );
System.out.println ( "dLongZoned: " + dLongZoned );
ライブコード
このクラスの実行 ライブコードIdeOne.com.
dShort:PT56M
dLong:PT13H
dShortZoned:PT56M
dLongZoned:PT13H
どなたでもこのページでは、ご出力フォーマットを用い時間スタイルなど 00:56
が曖昧で混乱し、回避されるべきである。の Duration
クラスの代わりに使用基準 ISO8601形式のための時間.上記を参照の結果五十六分で十分です。
約java.時間
の java.時間 枠組みがJava8以降である。これらのクラスsupplantの面倒古 レガシー 日付-時間の授業など java.util.Date
, Calendar
, & SimpleDateFormat
.
の Joda-時間 プロジェクトは、 メンテナンスモード,助言への移行 java.時間 ます。
詳細は、 Oracleのチュートリアル.検索スタックオーバーフローのための多くの例で説明しています。仕様 JSR310.
入手先のjava.時間の授業で
- Java SE8 や SE9 以降
- ですのでお問い合わせ下さい。
- 一部の標準のJava APIでは、同梱の実装です。
- Java9を追加し若干の特徴と問題を修正
- Java SE6 や SE7
- 多くのjava.時間の機能はバに移植されるJava6&7 ThreeTen-Backport.
- Android
- の ThreeTenABP プロジェクトに対応 ThreeTen-Backport (上記)Android注目する必要があると主張した。
- 見 使い方ThreeTenABP....
の ThreeTenインストール プロジェクトextends java.時間を追加します。このプロジェクトには、立地のためには、将来的な追加java.ます。すべての授業などはこちら Interval
, YearWeek
, YearQuarter
, は、 以上.