将日历日期格式化为受时区影响的 dd-MM-yyyy
Format calendar date to dd-MM-yyyy affected by timezone
我在将日历对象转换为可读字符串时遇到了一个大问题。
实际上我使用 df.format(cal.getTime()) 来获取格式化字符串,这不是很好,因为我从 cal.getTime() 获取的 Date 对象是不受时区影响。
请收回任何评论,例如 "use joda time"...
我正在寻找直接从日历对象转换为字符串的解决方案。
这些是我的格式化程序:
private DateFormat df = new SimpleDateFormat("HH:mm", Locale.GERMANY); // 13:42 Uhr
private DateFormat df2 = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.GERMANY); // 14.04.2012
如果你们尝试一下这段代码,您会发现 Date 对象不受时区影响。
// this date is at wintertime
long milli = 1445945400000l; // CET - central european time
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(milli);
System.out.println(" ");
System.out.println("Kalender setTimeInMillis(" + milli + ");");
System.out.println("Daylight Time ? = " + cal.getTimeZone().useDaylightTime());
System.out.println("Date Time = " + cal.getTime());
System.out.println("Kalender Tag = " + cal.get(Calendar.DATE) + " Monat = " + (cal.get(Calendar.MONTH) + 1) + " Jahr = " + cal.get(Calendar.YEAR));
System.out.println("Kalender Uhrzeit = " + cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND));
cal.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
System.out.println(" ");
System.out.println("Kalender setTimeZone(TimeZone.getTimeZone(\"Europe/Berlin\");");
System.out.println("Daylight Time ? = " + cal.getTimeZone().useDaylightTime());
System.out.println("Date Time = " + cal.getTime());
System.out.println("Kalender Tag = " + cal.get(Calendar.DATE) + " Monat = " + (cal.get(Calendar.MONTH) + 1) + " Jahr = " + cal.get(Calendar.YEAR));
System.out.println("Kalender Uhrzeit = " + cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND));
// this date is at summertime
long milliS = 1445609700000l; // CEST - central european summertime
Calendar calS = Calendar.getInstance();
calS.setTimeInMillis(milliS);
System.out.println(" ");
System.out.println("Kalender setTimeInMillis(" + milliS + ");");
System.out.println("Daylight Time ? = " + calS.getTimeZone().useDaylightTime());
System.out.println("Date Time = " + calS.getTime());
System.out.println("Kalender Tag = " + calS.get(Calendar.DATE) + " Monat = " + (calS.get(Calendar.MONTH) + 1) + " Jahr = " + calS.get(Calendar.YEAR));
System.out.println("Kalender Uhrzeit = " + calS.get(Calendar.HOUR_OF_DAY) + ":" + calS.get(Calendar.MINUTE) + ":" + calS.get(Calendar.SECOND));
calS.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
System.out.println(" ");
System.out.println("Kalender setTimeZone(TimeZone.getTimeZone(\"Europe/Berlin\");");
System.out.println("Daylight Time ? = " + calS.getTimeZone().useDaylightTime());
System.out.println("Date Time = " + calS.getTime());
System.out.println("Kalender Tag = " + calS.get(Calendar.DATE) + " Monat = " + (calS.get(Calendar.MONTH) + 1) + " Jahr = " + calS.get(Calendar.YEAR));
System.out.println("Kalender Uhrzeit = " + calS.get(Calendar.HOUR_OF_DAY) + ":" + calS.get(Calendar.MINUTE) + ":" + calS.get(Calendar.SECOND));
输出
Kalender setTimeInMillis(1445945400000);
Daylight Time ? = false
Date Time** = Tue Oct 27 11:30:00 GMT 2015
Kalender Tag = 27 Monat = 10 Jahr = 2015
Kalender Uhrzeit = 11:30:0
Kalender setTimeZone(TimeZone.getTimeZone("Europe/Berlin");
Daylight Time ? = true
Date Time = Tue Oct 27 11:30:00 GMT 2015
Kalender Tag = 27 Monat = 10 Jahr = 2015
Kalender Uhrzeit = 12:30:0
Kalender setTimeInMillis(1445609700000);
Daylight Time ? = false
Date Time = Fri Oct 23 14:15:00 GMT 2015
Kalender Tag = 23 Monat = 10 Jahr = 2015
Kalender Uhrzeit = 14:15:0
Kalender setTimeZone(TimeZone.getTimeZone("Europe/Berlin");
Daylight Time ? = true
Date Time = Fri Oct 23 14:15:00 GMT 2015
Kalender Tag = 23 Monat = 10 Jahr = 2015
Kalender Uhrzeit = 16:15:0
您需要设置格式化程序的时区,一个简单的例子:
SimpleDateFormat df = new SimpleDateFormat();
Calendar cal1 = Calendar.getInstance(TimeZone.getTimeZone("GMT+4:00"));
df.setTimeZone(cal1.getTimeZone());
System.out.println(df.format(cal1.getTime()));
Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("GMT-3:00"));
df.setTimeZone(cal2.getTimeZone());
System.out.println(df.format(cal2.getTime()));
输出:
10/30/15 1:02 PM
10/30/15 6:02 AM
请注意 java.util.Date 对象本身不包含任何时区信息 - 您不能在 Date 对象上设置时区。 Date 对象唯一包含的是自 "epoch" - 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数。
见
日期有自己的时区
令人困惑的是,java.util.Date 被分配了一个使用 JVM 当前默认时区的内部时区。您无法获取或设置该区域。 java.util.Calendar class 已添加到 Java 以处理时区和其他此类问题。
从纪元开始计数
long milli = 1445945400000l; // CET - central european time
通常这样的数字是 UTC(格林威治标准时间)的纪元计数,而不是任何特定时区。从该数字创建日期时间对象后,您可以分配要应用的时区。
提示:在整数文字上使用大写 L
以避免在许多字体中看起来像 1
。
java.time
这些 classes 现在已经被 Java 8 及更高版本中内置的 java.time 框架淘汰了。新的 classes 更明智且更易于使用。
时区
一个时区不止一个offset-from-UTC. A time zone is an offset plus a set of past, present, and future rules for handling anomalies such as Daylight Saving Time. Use a proper time zone such as Europe/Berlin
。避免使用甚至考虑 3-4 个字母的代码,例如 CET
& CEST
;它们既不是标准化的也不是唯一的。
示例代码
首先我们得到一个 Instant
,UTC 时间轴上的一个时刻,来自从纪元开始计数。
long milliSecondsFromEpochInUtc = 1445945400000L;
Instant instant = Instant.ofEpochMilli ( milliSecondsFromEpochInUtc );
然后我们分配所需的时区以获得ZonedDateTime
。
ZoneId zoneId = ZoneId.of ( "Europe/Berlin" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
对于输出,格式化程序默认使用 ZonedDateTime 对象的指定时区。
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime ( FormatStyle.MEDIUM ).withLocale ( Locale.GERMANY );
String output1 = zdt.format ( formatter );
如果指定,格式化程序可以选择应用不同的时区。
String output2 = zdt.format ( formatter.withZone ( ZoneId.of ( "America/Montreal" ) ) );
转储到控制台。
System.out.println ( "instant (UTC): " + instant );
System.out.println ( "zdt: " + zdt );
System.out.println ( "Berlin time zone: " + output1 );
System.out.println ( "Montréal time zone: " + output2 );
当运行。请注意,所有这些都代表时间轴上的同一时刻。他们的表达方式各不相同,但都表示同一时刻。
instant (UTC): 2015-10-27T11:30:00Z
zdt: 2015-10-27T12:30+01:00[Europe/Berlin]
Berlin time zone: 27.10.2015 12:30:00
Montréal time zone: 27.10.2015 07:30:00
我在将日历对象转换为可读字符串时遇到了一个大问题。
实际上我使用 df.format(cal.getTime()) 来获取格式化字符串,这不是很好,因为我从 cal.getTime() 获取的 Date 对象是不受时区影响。
请收回任何评论,例如 "use joda time"...
我正在寻找直接从日历对象转换为字符串的解决方案。
这些是我的格式化程序:
private DateFormat df = new SimpleDateFormat("HH:mm", Locale.GERMANY); // 13:42 Uhr
private DateFormat df2 = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.GERMANY); // 14.04.2012
如果你们尝试一下这段代码,您会发现 Date 对象不受时区影响。
// this date is at wintertime
long milli = 1445945400000l; // CET - central european time
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(milli);
System.out.println(" ");
System.out.println("Kalender setTimeInMillis(" + milli + ");");
System.out.println("Daylight Time ? = " + cal.getTimeZone().useDaylightTime());
System.out.println("Date Time = " + cal.getTime());
System.out.println("Kalender Tag = " + cal.get(Calendar.DATE) + " Monat = " + (cal.get(Calendar.MONTH) + 1) + " Jahr = " + cal.get(Calendar.YEAR));
System.out.println("Kalender Uhrzeit = " + cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND));
cal.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
System.out.println(" ");
System.out.println("Kalender setTimeZone(TimeZone.getTimeZone(\"Europe/Berlin\");");
System.out.println("Daylight Time ? = " + cal.getTimeZone().useDaylightTime());
System.out.println("Date Time = " + cal.getTime());
System.out.println("Kalender Tag = " + cal.get(Calendar.DATE) + " Monat = " + (cal.get(Calendar.MONTH) + 1) + " Jahr = " + cal.get(Calendar.YEAR));
System.out.println("Kalender Uhrzeit = " + cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND));
// this date is at summertime
long milliS = 1445609700000l; // CEST - central european summertime
Calendar calS = Calendar.getInstance();
calS.setTimeInMillis(milliS);
System.out.println(" ");
System.out.println("Kalender setTimeInMillis(" + milliS + ");");
System.out.println("Daylight Time ? = " + calS.getTimeZone().useDaylightTime());
System.out.println("Date Time = " + calS.getTime());
System.out.println("Kalender Tag = " + calS.get(Calendar.DATE) + " Monat = " + (calS.get(Calendar.MONTH) + 1) + " Jahr = " + calS.get(Calendar.YEAR));
System.out.println("Kalender Uhrzeit = " + calS.get(Calendar.HOUR_OF_DAY) + ":" + calS.get(Calendar.MINUTE) + ":" + calS.get(Calendar.SECOND));
calS.setTimeZone(TimeZone.getTimeZone("Europe/Berlin"));
System.out.println(" ");
System.out.println("Kalender setTimeZone(TimeZone.getTimeZone(\"Europe/Berlin\");");
System.out.println("Daylight Time ? = " + calS.getTimeZone().useDaylightTime());
System.out.println("Date Time = " + calS.getTime());
System.out.println("Kalender Tag = " + calS.get(Calendar.DATE) + " Monat = " + (calS.get(Calendar.MONTH) + 1) + " Jahr = " + calS.get(Calendar.YEAR));
System.out.println("Kalender Uhrzeit = " + calS.get(Calendar.HOUR_OF_DAY) + ":" + calS.get(Calendar.MINUTE) + ":" + calS.get(Calendar.SECOND));
输出
Kalender setTimeInMillis(1445945400000);
Daylight Time ? = false
Date Time** = Tue Oct 27 11:30:00 GMT 2015
Kalender Tag = 27 Monat = 10 Jahr = 2015
Kalender Uhrzeit = 11:30:0
Kalender setTimeZone(TimeZone.getTimeZone("Europe/Berlin");
Daylight Time ? = true
Date Time = Tue Oct 27 11:30:00 GMT 2015
Kalender Tag = 27 Monat = 10 Jahr = 2015
Kalender Uhrzeit = 12:30:0
Kalender setTimeInMillis(1445609700000);
Daylight Time ? = false
Date Time = Fri Oct 23 14:15:00 GMT 2015
Kalender Tag = 23 Monat = 10 Jahr = 2015
Kalender Uhrzeit = 14:15:0
Kalender setTimeZone(TimeZone.getTimeZone("Europe/Berlin");
Daylight Time ? = true
Date Time = Fri Oct 23 14:15:00 GMT 2015
Kalender Tag = 23 Monat = 10 Jahr = 2015
Kalender Uhrzeit = 16:15:0
您需要设置格式化程序的时区,一个简单的例子:
SimpleDateFormat df = new SimpleDateFormat();
Calendar cal1 = Calendar.getInstance(TimeZone.getTimeZone("GMT+4:00"));
df.setTimeZone(cal1.getTimeZone());
System.out.println(df.format(cal1.getTime()));
Calendar cal2 = Calendar.getInstance(TimeZone.getTimeZone("GMT-3:00"));
df.setTimeZone(cal2.getTimeZone());
System.out.println(df.format(cal2.getTime()));
输出:
10/30/15 1:02 PM
10/30/15 6:02 AM
请注意 java.util.Date 对象本身不包含任何时区信息 - 您不能在 Date 对象上设置时区。 Date 对象唯一包含的是自 "epoch" - 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数。
见
日期有自己的时区
令人困惑的是,java.util.Date 被分配了一个使用 JVM 当前默认时区的内部时区。您无法获取或设置该区域。 java.util.Calendar class 已添加到 Java 以处理时区和其他此类问题。
从纪元开始计数
long milli = 1445945400000l; // CET - central european time
通常这样的数字是 UTC(格林威治标准时间)的纪元计数,而不是任何特定时区。从该数字创建日期时间对象后,您可以分配要应用的时区。
提示:在整数文字上使用大写 L
以避免在许多字体中看起来像 1
。
java.time
这些 classes 现在已经被 Java 8 及更高版本中内置的 java.time 框架淘汰了。新的 classes 更明智且更易于使用。
时区
一个时区不止一个offset-from-UTC. A time zone is an offset plus a set of past, present, and future rules for handling anomalies such as Daylight Saving Time. Use a proper time zone such as Europe/Berlin
。避免使用甚至考虑 3-4 个字母的代码,例如 CET
& CEST
;它们既不是标准化的也不是唯一的。
示例代码
首先我们得到一个 Instant
,UTC 时间轴上的一个时刻,来自从纪元开始计数。
long milliSecondsFromEpochInUtc = 1445945400000L;
Instant instant = Instant.ofEpochMilli ( milliSecondsFromEpochInUtc );
然后我们分配所需的时区以获得ZonedDateTime
。
ZoneId zoneId = ZoneId.of ( "Europe/Berlin" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
对于输出,格式化程序默认使用 ZonedDateTime 对象的指定时区。
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime ( FormatStyle.MEDIUM ).withLocale ( Locale.GERMANY );
String output1 = zdt.format ( formatter );
如果指定,格式化程序可以选择应用不同的时区。
String output2 = zdt.format ( formatter.withZone ( ZoneId.of ( "America/Montreal" ) ) );
转储到控制台。
System.out.println ( "instant (UTC): " + instant );
System.out.println ( "zdt: " + zdt );
System.out.println ( "Berlin time zone: " + output1 );
System.out.println ( "Montréal time zone: " + output2 );
当运行。请注意,所有这些都代表时间轴上的同一时刻。他们的表达方式各不相同,但都表示同一时刻。
instant (UTC): 2015-10-27T11:30:00Z
zdt: 2015-10-27T12:30+01:00[Europe/Berlin]
Berlin time zone: 27.10.2015 12:30:00
Montréal time zone: 27.10.2015 07:30:00