Java日历从今天起10天,并将时间设置为12:00失败

时间:2018-04-01 11:56:04

标签: java android date

我想在今天前10天获得,并将时间设置为午夜12点

我已经发现一天有24小时,所以10天会有240小时,所以我有

Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR, cal.get(Calendar.HOUR) - 240);

上述方法有效但现在我想将时间设置为12:00

我试过了

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

在上述10天之后添加上述内容现在重置为今天。

可能出现什么问题?

4 个答案:

答案 0 :(得分:1)

如果您使用的是java.time库,则可以更轻松,您可以使用:

LocalDateTime date = LocalDateTime.of(
        LocalDate.now().minusDays(10),
        LocalTime.of(12, 0)
);

例如:

现在是:

2018-04-01T13:30

在10天之前,12点返回:

2018-03-22T12:00

答案 1 :(得分:1)

您使用https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html,方法set有此行为

  

set(f,value)将日历字段f更改为值。另外,它设定   内部成员变量,表示日历字段f已经过   改变。虽然日历字段f立即更改,但是   日历的时间值(以毫秒为单位)不会重新计算,直到下一个   调用get(),getTime(),getTimeInMillis(),add()或roll()。   因此,对set()的多次调用不会触发多次,不必要的   计算。使用set()更改日历字段的结果,   其他日历字段也可能会更改,具体取决于日历   字段,日历字段值和日历系统。此外,   get(f)不一定返回通过调用set设置的值   重新计算日历字段后的方法。具体细节   由具体日历类确定。

     

示例:考虑最初设置为8月31日的GregorianCalendar,   调用集(Calendar.MONTH,Calendar.SEPTEMBER)将日期设置为1999年9月31日。这是一个临时内部表示形式   如果随后调用getTime(),则解析为1999年10月1日。但是,一个   在调用getTime()之前调用set(Calendar.DAY_OF_MONTH,30)   将日期设置为1999年9月30日,因为没有重新计算   在set()之后。

您拨打set三次,结果是最后add次。因此,为了您的目的,您需要在{with} set之后使用方法{{1}}。

答案 2 :(得分:1)

TL;博士

ZonedDateTime.now(                   // Capture the current moment as seen through the wall-clock time used by the people of a certain region (a time zone).
    ZoneId.of( "Pacific/Auckland" )  // Specify a time zone using proper name, `continent/region`, never 3-4 pseudo-codes such as `PST`, `EST`, `IST`. 
)
.minusDays( 10 )                     // Go back in time ten days, adjusting for time-of-day as need be.
.toLocalDate()                       // Extract a date-only value.
.atStartOfDay(                       // Determine the first moment of that date in a certain time zone. Not always 00:00:00.
    ZoneId.of( "Pacific/Auckland" )  
)
.toString()                          // Generate a String in standard ISO 8601 format.
  

2018-03-23T00:00 + 13:00 [太平洋/奥克兰]

避免使用旧版日期时间类。

您正在使用 java.time 类在几年前取代的麻烦的旧日期时间类。

java.time

而不是Calendar,使用ZonedDateTime代表某个地区(时区)的人使用的挂钟时间在时间​​轴上的时刻。

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

如果未指定时区,则JVM会隐式应用其当前的默认时区。该默认值可能随时更改,因此您的结果可能会有所不同。最好明确指定您期望/预期的时区作为参数。

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

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Capture the current moment.

如果要使用JVM的当前默认时区,请求它并作为参数传递。如果省略,则隐式应用JVM的当前默认值。最好是明确的,因为默认情况下可以在运行时期间由JVM中任何应用程序的任何线程中的任何代码随时更改

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.
ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Capture the current moment.

数学

使用Period指定未附加到年 - 月 - 日时间轴的时间跨度。

Period p = Period.ofDays( 10 ) ;

回到过去。夏令时(DST)等异常会自动处理,并根据需要调整时间。

ZonedDateTime zdtTenDaysAgo = zdt.minus( p ) ; 
“午夜”是一个诡计多端的概念,含糊不清。相反,专注于“一天中的第一时刻”的想法。

始终让 java.time 确定第一时刻。不要假设这一天从00:00:00开始。 DST等异常意味着这一天可能会在另一个时间开始,例如01:00:00。要获得第一个时刻,请提取仅日期LocalDate对象。指定时区以确定该日期何时开始。

LocalDate ldTenDaysAgo = zdtTenDaysAgo.toLocalDate() ;
ZonedDateTime zdtTenDaysAgoStartOfDay = ldTenDaysAgo.atStartOfDay( z ) ;

如果您想查看与UTC相同的时刻,请提取Instant

Instant instant = zdtTenDaysAgoStartOfDay.toInstant() ;

关于 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类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 3 :(得分:0)

要添加或减去,您应该使用static void Main(string[] args) { var arr1 = new[] { "000", "110" }; var arr2 = new[] { "111", "011", "000" }; var arr3 = new[] { "101", "000" }; var result = IsAllHaveMoreThen1SequnceDuplicate(new List<string[]> {arr1, arr2, arr3}); } private static bool IsAllHaveMoreThen1SequnceDuplicate(List<string[]> arrays) { if (arrays == null || arrays.Count == 0) { return false; } var firstArray = arrays[0]; for (var i = 1; i < arrays.Count; i++) { var isHaveMoreThen1SequnceDuplicate = IsHaveMoreThen1SequnceDuplicate(firstArray, arrays[i]); if (!isHaveMoreThen1SequnceDuplicate) { return false; } } return true; } private static bool IsHaveMoreThen1SequnceDuplicate(string[] arr1, string[] arr2) { var globalCounter = 0; foreach (var s1 in arr1) { foreach (var s2 in arr2) { var isSameSequence = IsSameSequence(s1, s2); if (isSameSequence) { globalCounter++; break; } } if (globalCounter == 2) { return true; } } return false; } private static bool IsSameSequence(string s1, string s2) { if (s1 == s2) { return true; } if (s1.Length != s2.Length) { return false; } var flags = new int[9]; for (int i = 0; i < s1.Length; i++) { var cInt = int.Parse(s1[i].ToString()); flags[cInt]++; } for (int i = 0; i < s2.Length; i++) { var cInt = int.Parse(s2[i].ToString()); flags[cInt]--; } return flags.All(f => f == 0); } 方法:

add

但要注意这一点,因为由于夏令时效应,一天并不总是与24小时相同:https://www.timeanddate.com/time/dst/transition.html

无论如何,Calendar是一个非常错误的类,最好使用java.time类(API级别26),如果java.time不可用则使用threetenbp:http://www.threeten.org/threetenbp/

请在此处查看如何在Android中进行配置:How to use ThreeTenABP in Android Project

要考虑DST效果,请使用ZonedDateTime:

cal.add(Calendar.HOUR, -240);

这将处理DST的复杂细节,包括DST在午夜开始而实际从凌晨1点开始的情况 - 时间会自动调整。

目前尚不清楚您是否需要午夜(00:00)或中午(12:00)。无论如何,如果你想要中午,只需使用// current date/time ZonedDateTime.now() // minus 10 days .minusDays(10) // set time to midnight .with(LocalTime.MIDNIGHT);