このGMTタイムスタンプをGMT + 13に変換したい:
2011-10-06 03:35:05
この非常に基本的なタスクを実行するために、DateFormat、TimeZone、Date、GregorianCalendarなどの約100種類の組み合わせを試しました。
このコードは、現在の時間に私が望むことをします:
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));
String newZealandTime = formatter.format(calendar.getTime());
しかし、私が望むのは、現在の時刻を使用するのではなく、時刻を設定することです。
私はこのような時間を設定しようとするときはいつでも見つけました:
calendar.setTime(new Date(1317816735000L));
ローカルマシンのTimeZoneが使用されます。何故ですか? "new Date()"がUTC + 0時間を返すとき、なぜミリ秒単位でTimeを設定すると、時間がUTCであると仮定しなくなるのですか?
以下が可能です:
助けてくれてありがとう:D
私にとって、それを行う最も簡単な方法は:
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
//Here you say to Java the initial timezone. This is the secret
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
//Will print in UTC
System.out.println(sdf.format(calendar.getTime()));
//Here you set to your timezone
sdf.setTimeZone(TimeZone.getDefault());
//Will print on your default Timezone
System.out.println(sdf.format(calendar.getTime()));
コンピューター時間がどのように機能するかを理解することは非常に重要です。そうは言っても、リアルタイムのようにコンピューター時間を処理するのに役立つAPIが作成された場合、リアルタイムのように扱うことができるように動作するはずです。ほとんどの場合これは事実ですが、注意が必要ないくつかの主要な見落としがあります。
とにかく脱線!! UTCオフセットがある場合(GMTオフセットよりもUTCで作業する方がよい場合)、ミリ秒単位で時間を計算し、タイムスタンプに追加できます。 SQLタイムスタンプはJavaタイムスタンプとは異なる場合があります。これは、エポックからの経過の計算方法が常に同じではないためです-データベーステクノロジーとオペレーティングシステムによって異なります。
System.currentTimeMillis()をタイムスタンプとして使用することをお勧めします。これらは、SQLタイムスタンプをJava Dateオブジェクトなどに変換することを心配することなく、Javaでより一貫して処理できるためです。
オフセットを計算するには、次のようなものを試すことができます。
Long gmtTime =1317951113613L; // 2.32pm NZDT
Long timezoneAlteredTime = 0L;
if (offset != 0L) {
int multiplier = (offset*60)*(60*1000);
timezoneAlteredTime = gmtTime + multiplier;
} else {
timezoneAlteredTime = gmtTime;
}
Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(timezoneAlteredTime);
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
formatter.setCalendar(calendar);
formatter.setTimeZone(TimeZone.getTimeZone(timeZone));
String newZealandTime = formatter.format(calendar.getTime());
これがお役に立てば幸いです!
いつものように、理解できるように この記事 Javaの日時について読むことをお勧めします。
基本的な考え方は、「内部」でエポック以降すべてがUTCミリ秒で行われるということです。つまり、タイムゾーンをまったく使用せずに操作するのが最も簡単です。ただし、ユーザーの文字列形式は例外です。
したがって、提案された手順のほとんどはスキップします。
または、 Joda time を使用できます。私はそれがはるかに直感的なdatetime APIだと聞いたことがあります。
Instant.ofEpochMilli( 1_317_816_735_000L )
.atZone( ZoneId.of( "Pacific/Auckland" ) )
.format( DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( new Locale( "en" , "NZ" ) ) )
…また…
LocalDateTime.parse( "2011-10-06 03:35:05".replace( " " , "T" ) )
.atZone( ZoneId.of( "Pacific/Auckland" ) )
質問とほとんどの回答は、Javaの最も初期のバージョンの古いレガシー日時クラスを使用しています。これらの古いクラスは、面倒でわかりにくいことがわかっています。それらを避けてください。代わりに、Java.timeクラスを使用してください。
入力文字列は、ほぼ標準のISO 8601形式です。中央のSPACEをT
に置き換えるだけです。
String input = "2011-10-06 03:35:05".replace( " " , "T" );
LocalDateTime
入力にUTCからのオフセットまたはタイムゾーンに関する情報がないため、 LocalDateTime
として解析するようになりました。 LocalDateTime
にはオフセットやタイムゾーンの概念がないため、notはタイムライン上の実際の瞬間を表します。
LocalDateTime ldt = LocalDateTime.parse( input );
ZoneOffset
あなたはビジネスコンテキストから、この文字列の意図はUTCより13時間進んだ瞬間を表すことだと知っていると言っているようです。したがって、 ZoneOffset
をインスタンス化します。
ZoneOffset offset = ZoneOffset.ofHours( 13 ); // 13 hours ahead of UTC, in the far east of the globe.
OffsetDateTime
それを適用して OffsetDateTime
オブジェクトを取得します。これは、タイムライン上の実際の瞬間になります。
OffsetDateTime odt = ldt.atOffset( offset);
ZoneId
しかし、あなたはニュージーランドに言及します。そのため、特定のタイムゾーンを念頭に置いていました。タイムゾーンは、UTCからのオフセットプラス夏時間(DST)などの異常を処理するための一連のルールです。したがって、単なるオフセットではなく、ZoneId
をZonedDateTime
に指定できます。
適切なタイムゾーン名 を指定します。 EST
やIST
などの3〜4文字の略語は、真のタイムゾーンではなく、標準化されておらず、一意(!)でもないため、絶対に使用しないでください。たとえば、Pacific/Auckland
。
ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime
ZoneId
を適用します。
ZonedDateTime zdt = ldt.atZone( z );
タイムライン上の同じ瞬間に別のゾーンに簡単に調整できます。
ZoneId zParis = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdtParis = zdt.withZoneSameInstant( zParis ); // Same moment in time, but seen through lens of Paris wall-clock time.
1970年のUTCの開始からのミリ秒など、エポックからのカウントとして日時値を処理しないことを強くお勧めします。ただし、必要な場合は、そのような番号からInstant
を作成してください。
Instant instant = Instant.ofEpochMilli( 1_317_816_735_000L );
次に、必要に応じて、上記のタイムゾーンを割り当てて、UTCから移動します。
ZoneId z = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt = instant.atZone( z );
1_317_816_735_000L
の値は次のとおりです。
2011-10-05T12:12:15Z
(2011年10月5日水曜日12:12:15 GMT)2011-10-06T01:12:15+13:00[Pacific/Auckland]
(2011年10月6日木曜日、ニュージーランドオークランドの01:12:15)。標準の ISO 8601 形式で文字列を生成するには、単にtoString
を呼び出します。 ZonedDateTime
は、角かっこでタイムゾーンの名前を追加することにより、標準形式を賢く拡張することに注意してください。
String output = zdt.toString();
他の形式については、スタックオーバーフローで DateTimeFormatter
クラスを検索してください。すでに何度も取り上げました。
FormatStyle
および Locale
を指定します。
Locale l = new Locale( "en" , "NZ" );
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( l );
String output = zdt.format( f );
タイムゾーンにはロケールとは関係がないnothingがあることに注意してください。 Europe/Paris
日時を日本語および文化的規範で表示するか、Asia/Kolkata
日時をポルトガル語およびブラジルの文化的規範で表示することができます。
Java.time フレームワークはJava 8以降に組み込まれています。これらのクラスは、Java.util.Date
、.Calendar
、&Java.text.SimpleDateFormat
などの厄介な古い日時クラスに取って代わります。
Joda-Time プロジェクトは、現在 メンテナンスモード であり、Java.timeへの移行を推奨しています。
詳細については、 Oracle Tutorial を参照してください。また、多くの例と説明についてはStack Overflowを検索してください。
Java.time機能の多くは、 ThreeTen-Backport でJava 6および7にバックポートされ、さらに Android in ThreeTenABP ( 使用方法… を参照)。
ThreeTen-Extra プロジェクトは、追加のクラスでJava.timeを拡張します。このプロジェクトは、Java.timeに将来追加される可能性のある証明の場です。ここで、Interval
、YearWeek
、YearQuarter
などの便利なクラスを見つけることができます。
ソリューションは実際には非常に単純です(純粋な単純なJava):
System.out.println(" NZ Local Time: 2011-10-06 03:35:05");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localNZ = LocalDateTime.parse("2011-10-06 03:35:05",formatter);
ZonedDateTime zonedNZ = ZonedDateTime.of(localNZ,ZoneId.of("+13:00"));
LocalDateTime localUTC = zonedNZ.withZoneSameInstant(ZoneId.of("UTC")).toLocalDateTime();
System.out.println("UTC Local Time: "+localUTC.format(formatter));
出力は:
NZ Local Time: 2011-10-06 03:35:05
UTC Local Time: 2011-10-05 14:35:05
JavaにGMT + 13のタイムゾーンがあるとは思わないので、使用する必要があると思います。
Calendar calendar = Calendar.getInstance();
//OR Calendar.getInstance(TimeZone.getTimeZone("GMT"));
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY)+13);
Date d = calendar.getTime();
(「GMT」をそのタイムゾーンに変更し、コードの2行目を削除する場合)
OR
SimpleDateFormat df = new SimpleDateFormat();
df.setTimeZone(TimeZone.getTimeZone("GMT+13"));
System.out.println(df.format(c.getTime()));
特定の時刻/日付を設定する場合は、次も使用できます。
calendar.set(Calendar.DATE, 15);
calendar.set(Calendar.MONTH, 3);
calendar.set(Calendar.YEAR, 2011);
calendar.set(Calendar.HOUR_OF_DAY, 13);
calendar.set(Calendar.MINUTE, 45);
calendar.set(Calendar.SECOND, 00);
Java.util.Date/Calendarクラスは混乱しているため、使用しないでください。
更新:Joda-Timeプロジェクトはメンテナンスモードです。チームは、Java.timeクラスへの移行を推奨しています。
Joda-Time 2.3ライブラリを使用した答えは次のとおりです。非常に簡単。
サンプルコードで述べたように、可能な限り名前付きタイムゾーンを使用して、プログラミングで 夏時間 (DST)およびその他の異常を処理できるようにすることをお勧めします。
スペースの代わりに文字列の中央にT
を配置した場合、最初の2行のコードをスキップして、文字列を解析するフォーマッタを処理できます。 DateTime コンストラクターは ISO 8601 形式の文字列を取ることができます。
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
// Parse string as a date-time in UTC (no time zone offset).
DateTimeFormatter formatter = org.joda.time.format.DateTimeFormat.forPattern( "yyyy-MM-dd' 'HH:mm:ss" );
DateTime dateTimeInUTC = formatter.withZoneUTC().parseDateTime( "2011-10-06 03:35:05" );
// Adjust for 13 hour offset from UTC/GMT.
DateTimeZone offsetThirteen = DateTimeZone.forOffsetHours( 13 );
DateTime thirteenDateTime = dateTimeInUTC.toDateTime( offsetThirteen );
// Hard-coded offsets should be avoided. Better to use a desired time zone for handling Daylight Saving Time (DST) and other anomalies.
// Time Zone list… http://joda-time.sourceforge.net/timezones.html
DateTimeZone timeZoneTongatapu = DateTimeZone.forID( "Pacific/Tongatapu" );
DateTime tongatapuDateTime = dateTimeInUTC.toDateTime( timeZoneTongatapu );
それらの値をダンプ…
System.out.println( "dateTimeInUTC: " + dateTimeInUTC );
System.out.println( "thirteenDateTime: " + thirteenDateTime );
System.out.println( "tongatapuDateTime: " + tongatapuDateTime );
実行すると…
dateTimeInUTC: 2011-10-06T03:35:05.000Z
thirteenDateTime: 2011-10-06T16:35:05.000+13:00
tongatapuDateTime: 2011-10-06T16:35:05.000+13:00
オフセット値を使用してこれを処理できます
public static long convertDateTimeZone(long lngDate, String fromTimeZone,
String toTimeZone){
TimeZone toTZ = TimeZone.getTimeZone(toTimeZone);
Calendar toCal = Calendar.getInstance(toTZ);
TimeZone fromTZ = TimeZone.getTimeZone(fromTimeZone);
Calendar fromCal = Calendar.getInstance(fromTZ);
fromCal.setTimeInMillis(lngDate);
toCal.setTimeInMillis(fromCal.getTimeInMillis()
+ toTZ.getOffset(fromCal.getTimeInMillis())
- TimeZone.getDefault().getOffset(fromCal.getTimeInMillis()));
return toCal.getTimeInMillis();
}
テストコードスニペット:
System.out.println(new Date().getTime())
System.out.println(convertDateTimeZone(new Date().getTime(), TimeZone
.getDefault().getID(), "EST"));
出力:1387353270742 1387335270742
私はこのコードを試してみました
try{
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss Z");
Date datetime = new Date();
System.out.println("date "+sdf.format(datetime));
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("GMT "+ sdf.format(datetime));
sdf.setTimeZone(TimeZone.getTimeZone("GMT+13"));
System.out.println("GMT+13 "+ sdf.format(datetime));
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("utc "+sdf.format(datetime));
Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));
String newZealandTime = formatter.format(calendar.getTime());
System.out.println("using calendar "+newZealandTime);
}catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
この結果を得る
date 06-10-2011 10:40:05 +0530
GMT 06-10-2011 05:10:05 +0000 // here getting 5:10:05
GMT+13 06-10-2011 06:10:05 +1300 // here getting 6:10:05
utc 06-10-2011 05:10:05 +0000
using calendar 06 Oct 2011 18:10:05 GMT+13:00
public Timestamp convertLocalTimeToServerDatetime(String dt,String timezone){
String clientDnT = dt ;// "2017-06-01 07:20:00";
try{
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(clientDnT);
TimeZone tz = TimeZone.getTimeZone(timezone.trim()); // get time zone of user
sdf.setTimeZone(tz);
// Convert to servertime zone
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
TimeZone tzInAmerica = TimeZone.getDefault();
sdf1.setTimeZone(tzInAmerica);
// assign date to date
String serverDate = sdf1.format(date);
// Convert to servertime zone to Timestamp
Date date2 = sdf.parse(serverDate);
Timestamp tsm = new Timestamp(date2.getTime());
return tsm;
}
catch(Exception e){
System.err.println(e);
}
return null;
}
現代的な答えを提供したいと思います。
日付と時刻を、あるGMTオフセットの文字列から、異なるGMTオフセットの異なる形式の文字列に変換する必要はありません。プログラムでは、適切な日時オブジェクトとしてインスタント(特定の時点)を保持します。文字列を出力する必要がある場合にのみ、オブジェクトを目的の文字列にフォーマットします。
入力の解析
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(' ')
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter();
String dateTimeString = "2011-10-06 03:35:05";
Instant instant = LocalDateTime.parse(dateTimeString, formatter)
.atOffset(ZoneOffset.UTC)
.toInstant();
ほとんどの場合、Instant
は特定の時点を保存するのに適しています。日付と時刻がGMTから来たことを明示する必要がある場合は、代わりにOffsetDateTime
を使用します。
出力の変換、フォーマット、印刷
ZoneId desiredZone = ZoneId.of("Pacific/Auckland");
Locale desiredeLocale = Locale.forLanguageTag("en-NZ");
DateTimeFormatter desiredFormatter = DateTimeFormatter.ofPattern(
"dd MMM uuuu HH:mm:ss OOOO", desiredeLocale);
ZonedDateTime desiredDateTime = instant.atZone(desiredZone);
String result = desiredDateTime.format(desiredFormatter);
System.out.println(result);
これは印刷されました:
2011年10月6日16:35:05 GMT + 13:00
あなたが言及したオフセット+13:00ではなく、タイムゾーンPacific/Aucklandを指定しました。あなたはニュージーランドの時間を望んでいると理解しました、そして太平洋/オークランドはこれを読者にもっとよく伝えます。タイムゾーンでは夏時間(DST)も考慮されるため、独自のコードでこれを考慮する必要はありません(ほとんどの場合)。
Oct
は英語なので、フォーマッターに明示的なロケールを指定することをお勧めします。 GMT
もローカライズされる可能性がありますが、すべてのロケールでGMT
を出力するだけだと思います。
書式パターン文字列のOOOO
はオフセットを印刷する方法の1つです。これは、z
から取得するタイムゾーンの略語を印刷するよりも、タイムゾーンの略語があいまいになることが多いためです。 NZDT
(ニュージーランドの夏時間)が必要な場合は、代わりにz
と入力してください。
あなたの質問
Java.timeの最新のクラスに関連して、番号付きの質問に答えます。
以下が可能です:
- オブジェクトに時間を設定します
いいえ、現代のクラスは不変です。最初から目的の日時を持つオブジェクトを作成する必要があります(これには、スレッドセーフを含む多くの利点があります)。
- (おそらく)初期タイムスタンプのタイムゾーンを設定します
コードで使用するatZone
メソッドは、指定されたタイムゾーンでZonedDateTime
を返します。他の日時クラスにも同様のメソッドがあり、atZoneSameInstant
または他の名前と呼ばれることもあります。
- タイムスタンプを新しいTimeZoneでフォーマットします
Java.timeでは、新しいタイムゾーンへの変換と書式設定は、示されているように2つの異なるステップです。
- 新しいタイムゾーンの時刻を含む文字列を返します。
はい、表示されているとおりに目的のタイムゾーンに変換し、表示されているとおりにフォーマットします。
私はこのような時間を設定しようとするといつでも見つかりました:
calendar.setTime(new Date(1317816735000L));
ローカルマシンのTimeZoneが使用されます。何故ですか?
それはあなたが考える方法ではなく、古いクラスでの(多くの)設計上の問題のほんのいくつかをうまく示しています。
Date
にはタイムゾーンがありません。印刷するときのみ、そのtoString
メソッドはローカルタイムゾーンを取得し、それを使用して文字列をレンダリングします。これはnew Date()
にも当てはまります。この振る舞いは、過去25年間で多くのプログラマを混乱させてきました。Calender
hashas a time zone。 calendar.setTime(new Date(1317816735000L));
を実行しても変更されません。Oracleチュートリアル:Date Time Java.timeの使用方法の説明。
指定された日付からUTC/GMTタイムスタンプを取得できます。
/**
* Get the time stamp in GMT/UTC by passing the valid time (dd-MM-yyyy HH:mm:ss)
*/
public static long getGMTTimeStampFromDate(String datetime) {
long timeStamp = 0;
Date localTime = new Date();
String format = "dd-MM-yyyy HH:mm:ss";
SimpleDateFormat sdfLocalFormat = new SimpleDateFormat(format);
sdfLocalFormat.setTimeZone(TimeZone.getDefault());
try {
localTime = (Date) sdfLocalFormat.parse(datetime);
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"),
Locale.getDefault());
TimeZone tz = cal.getTimeZone();
cal.setTime(localTime);
timeStamp = (localTime.getTime()/1000);
Log.d("GMT TimeStamp: ", " Date TimegmtTime: " + datetime
+ ", GMT TimeStamp : " + localTime.getTime());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return timeStamp;
}
渡された日付に基づいてUTC時間を返します。
UTCタイムスタンプのように現在の日付と時刻を逆にすることができます(逆も同様)
public static String getLocalTimeFromGMT(long gmtTimeStamp) {
try{
Calendar calendar = Calendar.getInstance();
TimeZone tz = TimeZone.getDefault();
calendar.setTimeInMillis(gmtTimeStamp * 1000);
// calendar.add(Calendar.MILLISECOND, tz.getOffset(calendar.getTimeInMillis()));
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
Date currenTimeZone = (Date) calendar.getTime();
return sdf.format(currenTimeZone);
}catch (Exception e) {
}
return "";
}
これが他の人の助けになることを願っています。ありがとう!!
2つの異なるタイムゾーンで期間または時間間隔を見つけるには
import org.joda.time.{DateTime, Period, PeriodType}
val s1 = "2019-06-13T05:50:00-07:00"
val s2 = "2019-10-09T11:30:00+09:00"
val period = new Period(DateTime.parse(s1), DateTime.parse(s2), PeriodType dayTime())
period.getDays
period.getMinutes
period.getHours
出力期間= P117DT13H40M
days = 117
minutes = 40
hours = 13
すべてのタイムゾーンの日付と時刻を表示します
import Java.util.Calendar;
import Java.util.TimeZone;
import Java.text.DateFormat;
import Java.text.SimpleDateFormat;
static final String ISO8601 = "yyyy-MM-dd'T'HH:mm:ssZ";
DateFormat dateFormat = new SimpleDateFormat(ISO8601);
Calendar c = Calendar.getInstance();
String formattedTime;
for (String availableID : TimeZone.getAvailableIDs()) {
dateFormat.setTimeZone(TimeZone.getTimeZone(availableID));
formattedTime = dateFormat.format(c.getTime());
System.out.println(formattedTime + " " + availableID);
}
簡単な方法は:
String dateText ="Thu, 02 Jul 2015 21:51:46";
long hours = -5; // time difference between places
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(E, dd MMM yyyy HH:mm:ss, Locale.ENGLISH);
LocalDateTime date = LocalDateTime.parse(dateText, formatter);
date = date.with(date.plusHours(hours));
System.out.println("NEW DATE: "+date);
出力
新しい日付:2015-07-02T16:51:46
あなたのアプローチは修正なしで機能します。
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
// Timestamp for 2011-10-06 03:35:05 GMT
calendar.setTime(new Date(1317872105000L));
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("GMT+13"));
// Prints 2011-10-06 16:35:05 GMT+13:00
System.out.println(formatter.format(calendar.getTime()));