我要做的是存储一个日期,以毫秒为单位,即当前时间的下一个午夜。所以,在晚上10:11发布,我想要一个代表明天早上12:00的日期。为此,我写了这行代码(知道一天有86400000毫秒):
long time = System.currentTimeMillis() + (86400000 - (System.currentTimeMillis() % 86400000));
该行旨在计算从上一个午夜开始的额外毫秒数,减去一整天的时间以查找到下一个午夜的时间,然后将其添加到当前时间,以便新值为下一个午夜的值午夜。无论出于何种原因,我用于调试的日期对象吐出" Wed Apr 20 20:00:00 EDT 2016"调用#toString()方法时。据说目前的时间是“2016年4月19日22:08:34 EDT 2016"在计算另一个日期的同时。
这意味着长毫秒实际上代表第二天晚上8点,而我希望它代表12:00 AM。任何人都可以帮助我发现我逻辑中的缺陷吗?
我很可能错过了一些明显的东西,所以请耐心等待。
注意:我也尝试过像这样计算时间:
long time = System.currentTimeMillis() - (System.currentTimeMillis() % 86400000) + 86400000;
但是这导致了相同的Date对象。
答案 0 :(得分:1)
您忘记调整时区。这是实现这一目标的简单方法。
TimeZone tz = TimeZone.getDefault();
long time = System.currentTimeMillis() + (86400000 - (System.currentTimeMillis() % 86400000));
time -= tz.getOffset(time);
System.out.println(new Date(time));
答案 1 :(得分:1)
你正在使用长期被取代的有缺陷的麻烦的日期时间类,首先是Joda-Time库,现在是它的继承者,Java 8及更高版本中内置的java.time框架。很多java.time已经被反向移植到Java 6& 7然后由ThreeTenABP项目改编为Android。
Instant
是UTC时间轴上的一个时刻,分辨率为纳秒。
Instant instant = Instant.now();
应用时区以获得ZonedDateTime
。时区对于确定日期至关重要。它可能已经在你的东边“明天”或西边的“昨天”。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( zoneId );
要获得当天的第一时刻,请不要认为时间是00:00:00.0
。夏令时等异常可能会导致不同的时间。让java.time确定那个时间。要做到这一点,我们必须通过LocalDate
课程。
LocalDate today = zdt.toLocalDate();
天数并不总是24小时,这在您的问题和代码中是不正确的假设。再次,让java.time通过调用plusDays
确定第二天。
LocalDate tomorrow = LocalDate.plusDays( 1 );
ZonedDateTime zdtTomorrowStart = tomorrow.atStartOfDay( zoneId );
我建议您避免将日期时间值作为纪元的计数进行跟踪。这容易出错,并且非常难以调试。当你从纳秒分辨率变为毫秒时,你将丢失数据。但如果你坚持的话。
long millis = zdtTomorrowStart.toInstant().toEpochMilli();
答案 2 :(得分:0)
直接时间计算可能很棘手,有很多极端情况。我认为避免它的最简单的解决方案是:
// now, with current timezone and locale
Calendar calendar = new GregorianCalendar();
// tomorrow
calendar.add(Calendar.DAY_OF_MONTH, 1);
// midnight
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
// get the resulting date
Date date = calendar.getTime();