我有一个字符串,用UTC表示时间。 考虑到夏令时,我需要将其转换为自美国东部时间午夜以来的毫秒数。 例如,在1月份,偏移量为5小时,但在6月4小时。
但是,下面的代码显示6月和1月的相同偏差为5小时。
变量tzOffset = -18000000
(= -5小时),无论日期月份。
请指教,
谢谢!
package TimeConversion;
import java.text.SimpleDateFormat;
import java.util.*;
public class TimeConversion {
public static void main(String[] args) throws Exception {
String utcTime = "20100101120000000";
SimpleDateFormat sdfIn = new SimpleDateFormat("yyyyMMddHHmmssSSS");
sdfIn.setTimeZone(TimeZone.getTimeZone("UTC"));
long utcMillis = sdfIn.parse(utcTime).getTime();
long tzOffset = TimeZone.getTimeZone("EST").getOffset(utcMillis);
long estMillis = utcMillis + tzOffset;
long estMillisSinceMidnight = estMillis % 86400000;
System.out.println("utcTime = " + utcTime + "\nestMillisSinceMidnight = " + estMillisSinceMidnight + "(" + 24.0 * estMillisSinceMidnight / 86.4e6 + ")");
}
}
答案 0 :(得分:0)
您可以从this calendar conversion utility窃取一些代码。你可能需要的是getLocalTime。免责声明:我写了它。
答案 1 :(得分:0)
Duration // Represent a span-of-time not attached to the timeline, on a scale of hours-minutes-seconds.
.between( // Instantiate a `Duration` by calculating time elapsed between a pair of moments.
LocalDateTime.parse( // Represent a date with time-of-day but lacking the context of a time zone or offset-from-UTC.
"20100101120000000" , // Tip: Use standard ISO 8601 formats instead of inventing your own.
DateTimeFormatter.ofPattern( "uuuuMMddHHmmssSSS" )
) // Returns a `LocalDateTime` object.
.atZone( // Place this date-with-time in the context of a particular time zone to determine a moment, a specific point on the timeline.
ZoneId.of( "America/Montreal" ) // Never use 2-4 character pseudo-zones such as `EST` or `EDT`. Real time zone names are in `Continent/Region` format.
) // Returns a `ZonedDateTime` object.
.toLocalDate() // Extracts the date-only portion from a `ZonedDateTime` object.
.atStartOfDay( // Determine the first moment of the day on that date as seen in a particular time zone.
ZoneId.of( "America/Montreal" )
) // Returns a `ZonedDateTime` object, rather than altering original. (immutable objects)
,
LocalDateTime.parse(
"20100101120000000" ,
DateTimeFormatter.ofPattern( "uuuuMMddHHmmssSSS" )
)
.atZone(
ZoneId.of( "America/Montreal" )
)
) // Returns a `Duration`.
.toMillis() // Returs a `long` integer.
请注意可能的数据丢失,因为任何毫秒或纳秒都不会以较粗的毫秒数来解释。
字符串utcTime =“ 20100101120000000”;
顺便说一句,而不是发明自己的格式,请使用标准的ISO 8601格式来交换日期时间值作为文本。该标准就是为此目的而发明的。
定义一种格式设置以匹配您的输入。
String input = "20100101120000000";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMddHHmmssSSS" ) ;
解析为LocalDateTime
对象,因为您的输入缺少时区或自UTC偏移的上下文。
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
如果您可以确定该日期和日期的预期时区,请应用ZoneId
以获得ZonedDateTime
。
我猜测EDT
是指北美或加勒比海地区的东海岸时间。那可以是任意数量的各种时区,例如America/New_York
,America/Louisville
等。我在这里任意猜测我的代码示例为America/Montreal
。
请勿使用2-4个字母的缩写,例如EDT
或EST
或IST
,因为它们不是真正的时区,不是标准化的,也不是甚至唯一的(!)。以Continent/Region
的格式指定proper time zone name,例如America/Montreal
,Africa/Casablanca
或Pacific/Auckland
。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
您希望获得从该时区中第一天的第一刻开始经过的时间,直到我们刚刚确定的ZonedDateTime
对象。
让 java.time 确定一天的第一时刻。在某些日期的某些区域中,日期可能不会从00:00开始。
LocalDate ld = zdt.toLocalDate() ;
ZonedDateTime zdtStartOfDay = ld.atStartOfDay( z ) ;
将经过时间计算为Duration
。提要输入为Instant
对象,它们表示与我们的ZonedDateTime
对象相同的时刻,但已调整为UTC(零小时-分钟-秒的偏移量)。
Duration d = Duration.between(
zdtStartOfDay.toInstant() ,
zdt.toInstant()
);
显然,您希望将时间跨度表示为毫秒数。小心可能的数据丢失,因为ZonedDateTime
和Instant
类解析为更精细的纳秒。
long millis = d.toMillis() ; // Report entire span-of-time as a count of milliseconds. Beware: possible data loss as any microseconds and nanoseconds are ignored.
请参见此code run live at IdeOne.com。我们得到了12个小时的结果。
d.toString():PT12H
毫里斯:43200000