Java日期(日历)在给定日期时间的情况下以当地时间计算一天的开始

所有,

在这个办公室度过了艰难的一天…我想在当地时间锻炼一天的开始,即午夜00:00:00,给定任何日历日期。

鉴于接下来的几天,我想在午夜当地时间计算当天的开始时间:

Time Start Day (Local) Start Day (GMT) 2011-03-27 00:00:00 GMT --> 2011-03-27 00:00:00 GMT --> 2011-03-27 00:00:00 GMT 2011-03-27 01:00:00 GMT --> 2011-03-27 00:00:00 GMT --> 2011-03-27 00:00:00 GMT 2011-03-27 02:00:00 GMT --> 2011-03-27 00:00:00 GMT --> 2011-03-27 00:00:00 GMT 2011-04-01 00:00:00 BST --> 2011-04-01 00:00:00 BST --> 2011-03-31 23:00:00 GMT 2011-10-30 00:00:00 BST --> 2011-10-30 00:00:00 BST --> 2011-10-29 23:00:00 GMT 2011-10-30 01:00:00 BST --> 2011-10-30 00:00:00 BST --> 2011-10-29 23:00:00 GMT 2011-10-30 01:00:00 GMT --> 2011-10-30 00:00:00 BST --> 2011-10-29 23:00:00 GMT 2011-11-01 00:00:00 GMT --> 2011-11-01 00:00:00 GMT --> 2011-11-01 00:00:00 GMT 

目前,我正在使用SimpleDateFormat将String Time解析为GregorianCalendar。 这给了我GMT / UTC时间来计算。

所以我有一些代码将字符串解析为GregorianCalendar:

 public GregorianCalendar getCalendar(String dateTime) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); GregorianCalendar cal = new GregorianCalendar(); cal.setTime(sdf.parse(dateTime, new ParsePosition(0))); return cal; } 

现在我需要将它设置为本地午夜:

 public void setToStartOfDayLocally(GregorianCalendar cal) { ???? } 

我不太确定我在日历上需要做什么。 不幸的是,我们不会在不久的将来转向JODA约会。 我也没有用我的例子来说明不同的时区。

有什么想法吗?

谢谢,

Andez

我认为这段代码可能会解决您的问题。 我用它来从当地时区的时间转换到另一个时区。

 public static Date convertLocalDateToDateTimezone( Date localDate, String timezone ) { TimeZone localTimeZone = TimeZone.getDefault(); TimeZone timezone = TimeZone.getTimeZone( timezone ); long gmtMillis = localDate.getTime(); long result = gmtMillis + timezone.getOffset( gmtMillis ) - localTimeZone.getOffset( gmtMillis ); return new Date( result ); } 

希望这可以帮助。

听起来你只想将所有时间部分设置为零。 您可以使用:

 cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); 

(假设您已正确设置日历中的时区。)

请注意,这不一定有效 – 在某些时区(例如巴西),在夏令时过渡午夜要么发生两次,要么根本不发生。

就个人而言,我会开始制作关于转移到Joda Time的声音,这使得所有这一切变得更加简单:)

java.time

您正在使用过时的课程。 在Java 8及更高版本中,使用内置的java.time框架。

不要假设这一天从00:00:00.0 。 由于夏令时(DST)等exception情况,每天的开始时间可能因时区而异。 让java.time类通过调用LocalDate::atStartOfDay来确定正确的时间。

避免使用3-4字母区域缩写,如BSTEST等。 它们既不标准也不独特。 使用适当的时区名称 。

Instant是UTC时间轴上的一个时刻。 应用时区以获取ZonedDateTime 。 从该日期时间( LocalDate提取仅日期值。 通过调用atStartOfDay应用时区以返回设置为该时区中当天第一时刻的ZonedDateTime

 Instant now = Instant.now(); ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId ); LocalDate localDate = zdt.toLocalDate(); ZonedDateTime zdtStart = localDate.atStartOfDay( zoneId ); 

提示:避免使用“午夜”这个词。 没有准确的定义。 有些人想到试图确定一天中的最后一刻是一个问题,因为一秒钟的无限可分。 有些人想到特殊字符串“24:00”表示午夜的行程,这进一步混淆了日期时间处理。 Joda-Time项目的经验告诉我们,最好将注意力集中在“一天中的第一时刻”,作为清晰而准确的意义。 此外,请注意,由于夏令时(DST)和某些时区的其他exception,第一时刻并非总是00:00:00 。 这就是为什么我们依赖atStartOfDay方法而不是硬编码零时间。