2017-01-21 5 views
0

yyyy-MM-dd HH:mmという形式の文字列が、UTCで表されます。 次のステップは、これをカレンダー(TimeZone UTC)に入れることです。Javaカレンダーと時刻UTCからBSTへ

さらに、UTCを「ヨーロッパ/ロンドン」のtimeZone(GMT/BST)に変換した別のカレンダーを作成する必要があります。

その後、「ヨーロッパ/ロンドン」カレンダーにDST(昼光節約オフセット)があるかどうかを検出できる必要があります。

以下のコードは、私がどれだけ持っているかを示し、デフォルトのシステムタイムゾーンがGMTのイギリスのコンピュータで正常に動作します。しかし、タイムゾーンがUTCのPCで実行すると失敗します。 DST_offset(常にゼロ)があるかどうかは私には分かりません。

 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 
    cal.set(Calendar.YEAR, 2016); 
    cal.set(Calendar.MONTH, 1); 
    cal.set(Calendar.DAY_OF_MONTH, 27); 
    cal.set(Calendar.HOUR_OF_DAY, 23); 
    cal.set(Calendar.MINUTE, 35); 
    cal.set(Calendar.SECOND, 0); 
    cal.set(Calendar.MILLISECOND, 0); 

    //This is required as Java Date JAN starts at 0. 
    int MonthCon = cal.get(Calendar.MONTH)-1; 
    cal.set(Calendar.MONTH, MonthCon); 
    Date d = cal.getTime(); 



    SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz"); 
    f.setTimeZone(TimeZone.getTimeZone("UTC")); 
    System.out.println("UTC: " + f.format(d)); 
    f.setTimeZone(TimeZone.getTimeZone("Europe/London")); 
    System.out.println("BST: " + f.format(d)); 

    //Creates a BST calendar of the same UTC time 
    String dateStrBST = f.format(d); 

    SimpleDateFormat curFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz"); 
    curFormater.setTimeZone(TimeZone.getTimeZone("Europe/London")); 
    Date dateObjBST = curFormater.parse(dateStrBST); 


    System.out.println("BSTNewDate: " + f.format(dateObjBST)); 


    Calendar calBST = Calendar.getInstance(TimeZone.getTimeZone("BST")); 
    calBST.setTime(dateObjBST); 

    System.out.println("Current TimeZone is : " + calBST.getTimeZone()); 

    int offset = calBST.get(Calendar.DST_OFFSET); 
    System.out.println("Day Light Savings: "+offset); 
    System.out.println("Transition Day: "+isDSTTransitionDay(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH),cal.get(Calendar.DAY_OF_MONTH))+" Transition Type: "+DSTtransitionType(cal.get(Calendar.YEAR),cal.get(Calendar.MONTH),cal.get(Calendar.DAY_OF_MONTH))); 

残念ながら、私は任意の特定の日が移行日であるかどうかを検出できるようにする必要があり、それはオン/オフまたはオン/オフDSTから変更日を言うことです。これもローカルコンピュータでは動作しますが、UTCのタイムゾーンでは動作しません。

private static boolean isDSTTransitionDay(int year, int month, int day) throws ParseException 
{ 
     Calendar calStartofDay = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 
     calStartofDay.set(Calendar.YEAR, year); 
     calStartofDay.set(Calendar.MONTH, month); 
     calStartofDay.set(Calendar.DAY_OF_MONTH, day); 
     calStartofDay.set(Calendar.HOUR_OF_DAY, 00); 
     calStartofDay.set(Calendar.MINUTE, 0); 
     calStartofDay.set(Calendar.SECOND, 1);    
     Date dStartofDay = calStartofDay.getTime();    

     SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz");       
     f.setTimeZone(TimeZone.getTimeZone("Europe/London"));    
     String dateStrUTCtoBST = f.format(dStartofDay); 


     SimpleDateFormat curFormater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssz"); 
     curFormater.setTimeZone(TimeZone.getTimeZone("Europe/London")); 
     Date dateObjBST = curFormater.parse(dateStrUTCtoBST); 
     Calendar calBST = Calendar.getInstance(); 
     calBST.setTime(dateObjBST);    

     int offsetStart = calBST.get(Calendar.DST_OFFSET); 

     calBST.add(Calendar.HOUR_OF_DAY, 23); 

     int offsetEnd = calBST.get(Calendar.DST_OFFSET); 
     //System.out.println("Start: "+offsetStart+" End: "+offsetEnd); 




     if (offsetEnd == offsetStart) 
     { 
      return false; 
     }else 
      { 
       //if(offsetStart<offsetEnd) {System.out.println("Transition to BST");}else{System.out.println("Transition to UTC/GMT");}; 
       return true; 
      } 
} 

したがって、UTCコンピュータでは、常にCalendar.DST_OFFSETを0に設定するため、悲惨な結果に終わります。私は途中で何かを間違いなく誤解していますので、どんな助けや明確さもいいと思います。

私は、カレンダーの残りの部分を使っているので、かなりカレンダーを使い続ける必要がありますが、Java8にはより多くの工夫が施されています。

+2

AFAIK、UTCにはDSTはありません。 GMTはUTCと等しくありません。 – SlumpA

+0

https://www.timeanddate.com/time/zone/uk/london – DevilCode

+1

「UTCコンピュータは常にCalendar.DST_OFFSETをゼロにしてしまうので、悲惨なことに失敗します」というのは、その定義が常にゼロのオフセットになるはずです。あなたはそれが何をすると思いますか?フランス語でBTW、UTCはロンドンではなくパリで1で定義されます。 –

答えて

0

あなたがコンピュータのタイムゾーンにcalBSTを設定

Calendar calBST = Calendar.getInstance(); 

使用している(UTCコンピュータ上に、それはUTCになります)。

calBST.setTime(dateObjBST);はタイムゾーンではなく時間を設定します。

getInstance(TimeZone zone)もお試しください。

いずれの場合においても

、私はこのようなあなたのコードを置き換えます:

Calendar calStartofDay = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 
calStartofDay.set(Calendar.YEAR, 2017); 
calStartofDay.set(Calendar.MONTH, 0); 
calStartofDay.set(Calendar.DAY_OF_MONTH, 21); 
calStartofDay.set(Calendar.HOUR_OF_DAY, 00); 
calStartofDay.set(Calendar.MINUTE, 0); 
calStartofDay.set(Calendar.SECOND, 1);    

Calendar calBST = Calendar.getInstance(TimeZone.getTimeZone("Europe/London")); 
calBST.setTimeInMillis(calStartofDay.getTimeInMillis()); 
// use this to check the time 
System.out.printf("%tc%n", calBST); 

また、カレンダーのドキュメントから、これについて注意してください:

セット(F値)カレンダーフィールドfを値に変更します。さらに、 をカレンダーフィールドfに が変更されたことを示す内部メンバー変数に設定します。カレンダーフィールドfはすぐに変更されますが、次の get()、getTime()、getTimeInMillis()、add()またはroll()が呼び出されるまで、 カレンダーの時間値はミリ秒単位で再計算されません。 したがって、set()を複数呼び出すと、複数の不要な の計算がトリガーされません。 set()を使用してカレンダーフィールドを変更した結果、 カレンダーフィールド のフィールド、カレンダーフィールド値、カレンダーシステムによっては、他のカレンダーフィールドも変更されることがあります。さらに、 get(f)は、カレンダーフィールドが再計算された後に、セット メソッドへの呼び出しによって設定された値を必ずしも返しません。詳細 は、具体的なカレンダークラスによって決定されます。

+0

それは試しました:カレンダーcalBST = Calendar.getInstance(TimeZone.getTimeZone( "Europe/London")); nbutの結果、java.lang.NullPointerExceptionが発生します。もし私が "UTC"を使っていればいい? – DevilCode

+0

私のPCでは、NullPointerExceptionを取得せず、別の都市で試しました... "getTimeZone" docs: "指定されたIDを理解できない場合は、指定したTimeZoneまたはGMTゾーンに戻ります。 " NPEを持っているのは非常に奇妙です。 – SlumpA

+0

AWS Lambdaでこれを実行しています...違いがあれば。 – DevilCode

2

正直言って、あなたのコードを読もうとしましたが、あなたが望むものを手に入れようとするあなたのやり方を本当に理解できませんでした。 Java 8を使用できる場合は、Java 8の日付と時刻のクラスを使用するように切り替えることをお勧めします。これらによってあなたの仕事はあまり複雑ではありません。デモのために、私は昨年10月30日に英国(およびEU)が夏時間(夏時間)から標準時間に戻った日を選択しました。

String originalDate = "2016-10-30 23:35"; 
LocalDateTime localTime = LocalDateTime.parse(originalDate, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")); 
ZonedDateTime utcTime = localTime.atZone(ZoneOffset.UTC); 
ZonedDateTime bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London")); 
// the summer time offset is how many milliseconds? 
long dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime()); 
System.out.println(dstOffset); // prints 0 

// try the same at start of day (midnight) 
utcTime = utcTime.toLocalDate().atStartOfDay(ZoneOffset.UTC); 
bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London")); 
dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime()); 
System.out.println(dstOffset); // prints 3600000 

// and next midnight 
utcTime = utcTime.plusDays(1); 
bstTime = utcTime.withZoneSameInstant(ZoneId.of("Europe/London")); 
dstOffset = ChronoUnit.MILLIS.between(utcTime.toLocalDateTime(), bstTime.toLocalDateTime()); 
System.out.println(dstOffset); // prints 0 
関連する問題