将CalendarDate()更改为Calendar对象,将日期更改回1970

时间:2017-11-07 18:55:41

标签: java android date datetime calendar

因此,我开始在名为startTime

的Calendar对象中获取当前时间
Calendar startTime = Calendar.getInstance();
Log.w(TAG, "CALENDAR BEFORE: " + startTime.getTime());

这很有效,因为我的日志说时间是当前时间(即TST Nov 07 07:50:10 CST 2017)。 但是我需要从Preference选项中获取一个时间,它会返回类似这样的内容:" 15:00"。这存储在String alarmPref

String alarmPref = preferences.getString(keyAlarm, "12:00");
Log.w(TAG, "AlarmReceiver: Alarm going to be set at: " + alarmPref);

这里变得棘手,我使用SimpleDateFormat将此String更改为Date,只需几小时和几分钟(添加日期内容崩溃)。

SimpleDateFormat format = new SimpleDateFormat("HH:mm", Locale.getDefault());

当我尝试将此时间添加到我首先创建的Calendar对象(startTime)时,它将时间更改为" Thu Jan 01 15:00:00 CST 1970",其中我有正确的时间但不是约会。

Date newDate = format.parse(alarmPref);
startTime.setTime(newDate);
Log.w(TAG, "CALENDAR AFTER SET: " + startTime.getTime());

我一直试图解决这个问题但是没有找到解决方案,也没有找到类似的问题。

3 个答案:

答案 0 :(得分:3)

如果您的目标是通过设置特定的时间来更改日期时间......

TL;博士

ZonedDateTime.of( 
    LocalDate.now( ZoneId.of( "America/Chicago" ) ) ,  // Get the current date for a particular place on Earth.
    LocalTime.parse( "15:00" ) ,                       // Specify the time-of-day.
    ZoneId.of( "America/Chicago" )                     // Assign the intended zone to the resulting `ZonedDateTime` object.
)

问题

您正在将表示时间的字符串解析为日期时间值。该解析方法假定您需要自1970-01-01T00:00:00Z的epoch reference date以来的第一天。所以你在1970年1月1日下午3点。这是所有正确记录的行为。但不是你想要的。

解决方案

避免遗留类

避免使用与最早版本的Java捆绑在一起的麻烦的旧日期时间类,例如Calendar。这些在几年前由java.time类在Java 8和Java 9中取代。对于早期的Android,请参阅下面的最后一个项目符号。

时区

指定您想要的时区。如果省略,则隐式应用JVM的当前默认时区。该默认值可能在运行时期间随时发生变化,因此不可靠。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如CSTESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的( !)。

ZoneId z = ZoneId.of( "America/Chicago" ) ;

时区对于确定日期和时间至关重要。对于任何给定的时刻,日期在全球范围内因地区而异。例如,在Paris France午夜后的几分钟是新的一天,而Montréal Québec中仍然是“昨天”。

ZonedDateTime zdtNow = ZonedDateTime.now( z ) ;

时间的日

对于仅限时间的值,没有任何日期且没有时区,请使用LocalTime类。

LocalTime lt = LocalTime.parse( "15:00" ) ;

仅限日期+时间

您想要相同的日期,但需要另一个时间。因此,在应用预期时区时,提取仅限日期的部分,与所需的时间相结合,以获得新的ZonedDateTime对象。

LocalDate ld = zdtNow.toLocalDate() ;
ZonedDateTime zdtTodayAtThreePm = ZonedDateTime.of( ld , lt , z ) ;

提示:通常最好在UTC而不是特定时区进行日志记录,序列化和数据交换。为此使用Instant类。您可以从Instant中提取ZonedDateTime

Instant instant = zdtTodayAtThreePm.toInstant() ;  // Always in UTC.

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

答案 1 :(得分:0)

我设法通过这样做得到了解决方法:

String alarmPref = preferences.getString(keyAlarm, "12:00");
Log.w(TAG, "AlarmReceiver: Alarm going to be set at: " + alarmPref);
SimpleDateFormat format = new SimpleDateFormat("HH:mm", Locale.getDefault());
Date newDate = format.parse(alarmPref);
//startTime.setTime(newDate);
startTime.set(Calendar.HOUR_OF_DAY, newDate.getHours());
startTime.set(Calendar.MINUTE, newDate..getHours());
startTime.set(Calendar.SECOND, 0);
Log.w(TAG, "CALENDAR AFTER SET: " + startTime.getTime());

我只设置HOURS和MINUTES(秒数为0),日期保持不变。但是不推荐使用方法.getHours()和.getHours(),有没有更奇特的方法呢?

答案 2 :(得分:0)

我在这里看不到任何问题。您要求SimpleDateFormat通过仅提供小时和分钟来解析日期。它默认输入中缺少的其他字段到开头时间,这不是您所期望的。显然,实现SimpleDateFormat的开发人员认为这种行为是合理的。

您只设置HOUR_OF_DAY和MINUTE的解决方法看起来不错。