我必须在我的 Java 应用程序中打印 EST 时间。我已使用以下方法将时区设置为 EST:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));
但是当在这个时区遵循夏令时时,我的代码不会打印正确的时间(它打印的时间少 1 小时)。
无论是否遵守夏令时,如何使代码始终读取正确的时间?
PS:我尝试将时区设置为 EDT,但并没有解决问题。
这是开始的问题:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));
应完全避免使用 3 个字母的缩写,以支持 TZDB 区域 ID。EST 是东部标准时间 -标准时间从不遵守 DST;这不是一个完整的时区名称。它是用于部分时区的名称。(不幸的是,我还没有找到一个关于“半时区”概念的好词。)
您想要一个完整的时区名称。例如,America/New_York
在东部时区:
TimeZone zone = TimeZone.getTimeZone("America/New_York");
DateFormat format = DateFormat.getDateTimeInstance();
format.setTimeZone(zone);
System.out.println(format.format(new Date()));
其他答案是正确的,尤其是Jon Skeet 的答案,但已经过时了。
这些旧的日期时间类已被Java 8 及更高版本中内置的java.time框架所取代。
如果您只是想要 UTC 的当前时间,请使用Instant
该类。
Instant now = Instant.now();
EST
不是时区,正如Jon Skeet 的正确答案中所解释的那样。这样的 3-4 个字母代码既不标准化也不唯一,进一步混淆了夏令时 (DST)。使用“大陆/地区”格式的正确时区名称。
也许您的意思是北美东海岸的东部标准时间?还是埃及标准时间?还是欧洲标准时间?
ZoneId zoneId = ZoneId.of( "America/New_York" );
ZoneId zoneId = ZoneId.of( "Africa/Cairo" );
ZoneId zoneId = ZoneId.of( "Europe/Lisbon" );
使用任何此类ZoneId
对象将当前时刻调整到特定时区以生成ZonedDateTime
对象。
ZonedDateTime zdt = ZonedDateTime.now( zoneId ) ;
通过从第一个对象生成另一个 ZonedDateTime 对象,将该 ZonedDateTime 调整到不同的时区。java.time 框架使用不可变对象而不是更改(变异)现有对象。
ZonedDateTime zdtGuam = zdt.withZoneSameInstant( ZoneId.of( "Pacific/Guam" ) ) ;
您可以输入“EST5EDT”,而不是输入“EST”作为时区。正如您所指出的,仅“EDT”不起作用。这将解决夏令时问题。代码行如下所示:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST5EDT"));
根据这个答案:
TimeZone tz = TimeZone.getTimeZone("EST");
boolean inDs = tz.inDaylightTime(new Date());
private static Long DateTimeNowTicks(){
long TICKS_AT_EPOCH = 621355968000000000L;
TimeZone timeZone = Calendar.getInstance().getTimeZone();
int offs = timeZone.getRawOffset();
if (timeZone.inDaylightTime(new Date()))
offs += 60 * 60 * 1000;
return (System.currentTimeMillis() + offs) * 10000 + TICKS_AT_EPOCH;
}
public static float calculateTimeZone(String deviceTimeZone) {
float ONE_HOUR_MILLIS = 60 * 60 * 1000;
// Current timezone and date
TimeZone timeZone = TimeZone.getTimeZone(deviceTimeZone);
Date nowDate = new Date();
float offsetFromUtc = timeZone.getOffset(nowDate.getTime()) / ONE_HOUR_MILLIS;
// Daylight Saving time
if (timeZone.useDaylightTime()) {
// DST is used
// I'm saving this is preferences for later use
// save the offset value to use it later
float dstOffset = timeZone.getDSTSavings() / ONE_HOUR_MILLIS;
// DstOffsetValue = dstOffset
// I'm saving this is preferences for later use
// save that now we are in DST mode
if (timeZone.inDaylightTime(nowDate)) {
Log.e(Utility.class.getName(), "in Daylight Time");
return -(ONE_HOUR_MILLIS * dstOffset);
} else {
Log.e(Utility.class.getName(), "not in Daylight Time");
return 0;
}
} else
return 0;
}
在java中,DateFormatter默认使用DST,为了避免夏令时(DST)你需要手动做一个技巧,
首先你必须得到DST偏移量,即应用了多少毫秒的DST,例如某处DST也是45分钟对于某些地方,它是 30 分钟
,但在大多数情况下,DST 是 1 小时
,您必须使用 Timezone 对象并检查日期是否属于 DST,然后您必须手动将 DST 的偏移量添加到其中。例如:
TimeZone tz = TimeZone.getTimeZone("EST");
boolean isDST = tz.inDaylightTime(yourDateObj);
if(isDST){
int sec= tz.getDSTSavings()/1000;// for no. of seconds
Calendar cal= Calendar.getInstance();
cal.setTime(yourDateObj);
cal.add(Calendar.Seconds,sec);
System.out.println(cal.getTime());// your Date with DST neglected
}
实现 TimeZone 类以将时区设置为 Calendar 负责夏令时。
java.util.TimeZone 表示时区偏移量,还计算夏令时。
示例代码:
TimeZone est_timeZone = TimeZoneIDProvider.getTimeZoneID(TimeZoneID.US_EASTERN).getTimeZone();
Calendar enteredCalendar = Calendar.getInstance();
enteredCalendar.setTimeZone(est_timeZone);