繁体   English   中英

SetDate()为Calendar对象以更改时间,将日期更改回1970

[英]SetDate() to Calendar object to change time, changes the date back to 1970

因此,我开始在名为startTime的Calendar对象中获取当前时间。

Calendar startTime = Calendar.getInstance();
Log.w(TAG, "CALENDAR BEFORE: " + startTime.getTime());

这很有效,因为我的日志显示时间是当前时间(即TST Nov 07 12:50:10 CST 2017)。 但是,我需要从“首选项”选项中抽出时间,该选项会向我返回类似“ 15:00”的信息。 这被存储在String alarmPref中

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

这是棘手的地方,我使用仅数小时和数分钟的SimpleDateFormat将此字符串更改为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());

我一直在尝试解决此问题,但没有找到解决方案,也没有类似的问题。

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

tl; dr

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开始的第一天。 因此您在1970年1月1日下午3点。这是所有正确记录的行为。 但不是您想要的。

避免遗留类

避免与最早的Java版本(例如Calendar捆绑在一起的麻烦的旧日期时间类。 这些在几年前被Java.time类替换为Java 8和Java 9。 对于较早的Android,请参阅下面的最新项目符号。

时区

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

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

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

时区对于确定日期和时间至关重要。 在任何给定时刻,日期都会在全球范围内变化。 例如, 法国巴黎午夜过后几分钟是新的一天,而在魁北克蒙特利尔仍然是“昨天”。

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类。 您可以从ZonedDateTime提取Instant ZonedDateTime

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

关于java.time

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

现在处于维护模式Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参见Oracle教程 并在Stack Overflow中搜索许多示例和说明。 规格为JSR 310

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

在哪里获取java.time类?

通过这样做,我设法解决了问题:

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(将秒设置为0),并且日期保持不变。 但是,不赞成使用方法.getHours()和.getHours(),是否有更理想的方法呢?

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM