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

时间:2011-09-28 15:37:17

标签: java date calendar

所有

在办公室度过了艰难的一天...我正在尝试在当地时间锻炼一天的开始,即午夜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

3 个答案:

答案 0 :(得分:0)

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

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

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

请注意,这不是必然有效 - 在某些时区(例如巴西),在夏令时过渡午夜要么出现两次,要么根本不出现。

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

答案 1 :(得分:0)

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

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 );
}

希望这有帮助。

答案 2 :(得分:0)

java.time

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

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

避免使用3-4个字母区域缩写,例如BSTEST等。它们既不标准也不独特。使用proper time zone names

InstantUTC中时间轴上的一个时刻。应用时区以获得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)和某些时区的其他异常,第一时刻总是00:00:00。这就是我们依赖atStartOfDay方法而不是硬编码零时间的原因。