如何计算两次之间的差

时间:2019-01-27 13:39:59

标签: java android date calendar

我要计算用户的睡眠时间,他应该在他睡觉时和醒来时输入,我应该计算出他睡了多少小时

例如,如果用户输入

His sleeping time : 11:00 pm

His waking up time : 7:30 am

The number of sleeping hours should be : 8:30 hrs

有什么方法可以轻松进行此计算

这是代码

cal.set(Calendar.HOUR_OF_DAY, 11);
        cal.set(Calendar.MINUTE, 0);
        sleepTimeOnOffDays = cal.getTime();

    private long subtractTwoDates(Date date1, Date date2) {

            Calendar calendar1 = Calendar.getInstance();
            Calendar calendar2 = Calendar.getInstance();
            calendar1.setTime(date1);
            calendar2.setTime(date2);
            long milsecs1 = calendar1.getTimeInMillis();
            long milsecs2 = calendar2.getTimeInMillis();
            long diff = milsecs2 - milsecs1;
            long dhours = diff / (60 * 60 * 1000);

            return Math.abs(dhours);
        }

4 个答案:

答案 0 :(得分:2)

从Java SE 8开始,我建议使用java.time API。对于Android用户,在API 26+中添加了java.time。

Java 8引入了用于日期和时间的新API,以解决旧版java.util.Date和java.util.Calendar的缺点。

使用java.time API计算两个日期时间之间的持续时间非常容易。

LocalDateTime localDateTime1 = LocalDateTime.now();
localDateTime1 = localDateTime1.withHour(23).withMinute(0).withSecond(0).withNano(0);

LocalDateTime localDateTime2 = LocalDateTime.now();
localDateTime2 = localDateTime2.plusDays(1).withHour(7).withMinute(30).withSecond(0).withNano(0);

Duration diff = Duration.between(localDateTime1, localDateTime2);

String hms = String.format("%d:%02d:%02d", 
                 diff.toHoursPart(),
                 diff.toMinutesPart(), 
                 diff.toSecondsPart());
System.out.println(hms);

-----------------------

Console output:
8:30:00

如果java.time API不适用于您的项目,例如因为您的项目尚未处于API级别26,那么我建议使用@Ole VV在评论中建议的ThreeTen Android Backport API下面。

语法与java.time API几乎相同。上面的代码段也适用于ThreeTen Android Backport API(例如已经提到的@Basil Bourque),但有一个例外。不幸的是,ThreeTen Android Backport API的Duration类没有提供用于从duration对象中提取小时部分,分钟部分等的辅助方法。相反,当您使用反向端口时,您需要先减去小时数,然后减去持续时间中的分钟数,这样仅剩秒数:

long hours = diff.toHours();
diff = diff.minusHours(hours);
long minutes = diff.toMinutes();
diff = diff.minusMinutes(minutes);
long seconds = diff.getSeconds();
String hms = String.format("%d:%02d:%02d", 
                 hours,
                 minutes, 
                 seconds);

另一个区别是您需要从org.threeten.bp包(而不是java.time包)中导入java.time类。

如果要使用ThreeTen Backport API,只需将其dependency包含到您的项目中即可。

答案 1 :(得分:2)

tl; dr

11:00 PM到7:30 AM = 7.5或8.0或8.5或9.5或其他一些小时数,具体取决于特定的日期和时区。

Duration.between(
    ZonedDateTime.of( 2019 , 1 , 23 , 23 , 0 , 0 , 0 , ZoneId.of( "Africa/Cairo" ) ) ,
    ZonedDateTime.of( 2019 , 1 , 24 , 7 , 30 , 0 , 0 , ZoneId.of( "Africa/Cairo" ) )
)
.toString()

请参阅此code run live at IdeOne.com

  

PT8H30M

计算经过时间需要日期,时间和时区

MarkusHänsel的

The Answer是正确的方法,但无法解决诸如夏令时(DST)之类的异常情况。

您的问题不太清楚。您是要使用24小时通用工作日来跟踪时间的一般想法吗?还是要跟踪实际时刻,例如前两天的睡眠时间,昨天的时间等等?

如果是后者,则不能使用LocalDateDate,因为根据定义,该类无法跟踪力矩。 LocalDateTime类缺少任何时区或UTC偏移量的概念。因此,LocalDateTime表示沿大约26-27小时(全球时区范围)范围内的潜在时刻。

以您的示例从11:00 pm到7:30 am,这意味着在特定时区的8.5个小时,该日期没有异常。但是在DST转换的一天,这可能意味着7.5个小时(“春季提前”)或9.5个小时(“回退”)。或者,例如去年North Korea adjusted their clock一天半小时,则为8.0小时(例如去年)。或在2007年Venezuela turned back time a half-hour… and then a decade later flipped back again时。这些更改比您可能意识到的发生得更多。全球各地的政客都对重新定义其时区的偏移表现出了浓厚的兴趣。

➥结果是您不能仅靠一天中的时间可靠地计算经过时间。您必须使用日期和时区

ZoneId

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

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;

ZonedDateTime

要跟踪时刻,请使用ZonedDateTime类。此类组合了日期,一天中的时间和时区。

LocalDate ldStart = LocalDate.of( 2019 , 1 , 23 ) ;
LocalTime ldStart = LocalTime.of( 23 , 0 ) ;
ZonedDateTime zdtStart = ZonedDateTime.of( ldStart , ltStart , z ) ;

还有停止时间。

LocalDate ldStop = LocalDate.of( 2019 , 1 , 24 ) ;  // Next day.
LocalTime ldStop = LocalTime.of( 7 , 30 ) ;
ZonedDateTime zdtStop = ZonedDateTime.of( ldStop , ltStop , z ) ;

使用Duration类来计算经过时间。

Duration d = Duration.between( zdtStart , zdtStop ) ;

ISO 8601

我建议您使用时间格式HH:MM:SS 报告经过时间。而是使用format defined for this purpose标准中的标准ISO 8601

因此,PT8H30M将是8.5小时。

java.time 类在解析/生成字符串时默认使用ISO 8601格式。

String output = d.toString() ;  // Generate `PT8H30M`.

然后解析。

Duration d = Duration.parse( "PT8H30M" ) ;

关于 java.time

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

目前位于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

答案 2 :(得分:0)

您可以使用SimpleDateFormat来获取输入。我使用的是预定义的输入,因为您希望计算两个给定时间之间的差。这是您的代码。请注意,我给出了24或12小时格式的答案。

获取睡眠时间和起床时间的价值

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
Date sleepingTime = simpleDateFormat.parse("22:00");
Date wakeUptime = simpleDateFormat.parse("07:00");

由于差异小于零,因此以12小时格式发生

long difference = sleepingTime.getTime() - wakeUpTime.getTime(); 
if(difference<0) {
  Date dateMax = simpleDateFormat.parse("24:00");
  Date dateMin = simpleDateFormat.parse("00:00");
  difference=(dateMax.getTime() -sleepingTime.getTime() )+(wakeUpTime.getTime()- 
  dateMin.getTime());
}

计算差异

//days and minutes are optional
int days = (int) (difference / (1000*60*60*24));  
int hours = (int) ((difference - (1000*60*60*24*days)) / (1000*60*60)); 
int min = (int) (difference - (1000*60*60*24*days) - (1000*60*60*hours)) / 
(1000*60);
Log.e("log_tag",hours+" hours"); 

我希望它能回答您的查询。谢谢:)

答案 3 :(得分:0)

只需尝试以下代码行,即可在几分钟内获得差异

import java.util.concurrent.TimeUnit; // predefined method from java 6.

  private long subtractTwoDates(Date date1, Date date2) {
    Long diffInMinutes=null,diff=null;  // just  declaration of variables
    diff = date1.getTime() - date2.getTime();
    diffInMinutes= TimeUnit.MILLISECONDS.toMinutes(diff);
    log.info("diff min : "+difInMin); 
    return  diffInMinutes; // returns long value in minutes.
}