简体   繁体   English

如何计算两次之间的差

[英]How to calculate the difference between two times

I want to calculate the sleeping time of user, he should enter when he slept and when he woke up and I should calculate how many hours he slept 我要计算用户的睡眠时间,他应该在他睡觉时和他醒来时输入,我应该计算出他睡了多少小时

For example if the user enter 例如,如果用户输入

His sleeping time : 11:00 pm

His waking up time : 7:30 am

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

Is there any way to make this calculation easily 有什么方法可以轻松进行此计算

This is the code 这是代码

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);
        }

From Java SE 8 onwards i would like to suggest using the java.time API. 从Java SE 8开始,我建议使用java.time API。 For Android users, java.time is added in API 26+ . 对于Android用户,在API 26+中添加了java.time

Java 8 introduced new APIs for Date and Time to address the shortcomings of the older java.util.Date and java.util.Calendar. Java 8引入了用于日期和时间的新API,以解决较旧的java.util.Date和java.util.Calendar的缺点。

Using the java.time API calculating the duration between 2 date times is very easy. 使用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

If the java.time API is not available for your project, because for example your project is not yet on API level 26, then i would recommend using the ThreeTen Android Backport API as suggested by @Ole VV in the comments below. 如果java.time API对于您的项目不可用,例如因为您的项目尚不处于API级别26,那么我建议使用@Ole VV在以下注释中建议的ThreeTen Android Backport API。

The Syntax is pretty much the same as the java.time API. 语法与java.time API几乎相同。 The code snippet above works for the ThreeTen Android Backport API as well (like @Basil Bourque already mentioned) with one exception. 上面的代码段也适用于ThreeTen Android Backport API(例如已经提到的@Basil Bourque),但有一个例外。 The Duration class of the ThreeTen Android Backport API unfortunately does not provide helper methods for extracting the hours part, minutes part etc. from the duration object. 不幸的是,ThreeTen Android Backport API的Duration类没有提供用于从duration对象中提取小时部分,分钟部分等的辅助方法。 Instead when you use the backport you need to subtract first the hours, then the minutes from the duration so only the seconds are left: 相反,当您使用反向端口时,您需要先减去小时数,然后再减去持续时间中的分钟数,因此只剩下秒数:

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);

Another difference is you need to import the java.time classes from the org.threeten.bp package (not the java.time package). 另一个区别是您需要从org.threeten.bp包(而不是java.time包)中导入java.time类。

If you want to use the ThreeTen Backport API, just include it's dependency to your project. 如果要使用ThreeTen Backport API,只需在项目中包含它的依赖项即可。

tl;dr TL;博士

11:00 PM to 7:30 AM = 7.5 or 8.0 or 8.5 or 9.5 or some other number of hours depending on the particular dates and time zone. 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()

See this code run live at IdeOne.com . 看到此代码在IdeOne.com上实时运行

PT8H30M PT8H30M

Calculating elapsed time requires date, time-of-day, and time zone 计算经过时间需要日期,时间和时区

The Answer by Markus Hänsel is headed the right way, but fails to account for anomalies such as Daylight Saving Time (DST). MarkusHänsel 的答案正确无误,但未能解决诸如夏令时(DST)之类的异常情况。

Your Question is not quite clear. 您的问题不太清楚。 Do you mean to track the general idea of time-of-day using generic 24-hour days? 您是要使用24小时通用工作日来跟踪时间的一般想法吗? Or do you mean to track actual moments, such as the time slept two days ago, the time slept yesterday, and so on? 还是要跟踪实际时刻,例如前两天的睡眠时间,昨天的时间等等?

If the latter, then you cannot use LocalDateDate as that class cannot, by definition, track moments. 如果是后者,则不能使用LocalDateDate ,因为根据定义,该类无法跟踪力矩。 The LocalDateTime class lacks any concept of time zone or offset-from-UTC. LocalDateTime类缺少任何时区或从UTC偏移的概念。 As such, a LocalDateTime represents potential moments along a range of about 26-27 hours (the range of time zones around the globe). 因此, LocalDateTime表示大约26-27小时(全球时区范围)内的潜在时刻。

Given your example of 11:00 pm to 7:30 am, that would mean 8.5 hours in a certain time zone with no anomalies on that date. 以您的示例从11:00 pm到7:30 am,这意味着在特定时区的8.5个小时,该日期没有异常。 But on a day of DST cut-over that might mean 7.5 hours (“Spring ahead”), or 9.5 hours (“Fall back”). 但是在DST转换的一天,这可能意味着7.5个小时(“春季提前”)或9.5个小时(“回退”)。 Or maybe 8.0 hours on day such as last year when North Korea adjusted their clock by a half-hour. 或许像去年那样,每天有8.0个小时, 朝鲜去年将时钟调整了半个小时。 Or when in 2007 Venezuela turned back time a half-hour… and then a decade later flipped back again . 或者说, 委内瑞拉在2007年将时间倒退了半小时……然后十年后又倒退了 These changes happen more often than you may realize. 这些更改比您可能意识到的发生得更多。 Politicians around the globe have shown a penchant for redefining the offset of their time zone(s). 全球各地的政客都对重新定义其时区的偏移表现出了浓厚的兴趣。

➥ The upshot is that you cannot reliably calculate elapsed time with only the time-of-day. shot结果是您不能仅靠一天中的时间可靠地计算经过时间。 You must use a date and a time zone . 必须使用日期和时区

ZoneId

Specify a proper time zone name in the format of Continent/Region , such as America/Montreal , Africa/Casablanca , or Pacific/Auckland . Continent/Region的格式指定正确的时区名称 ,例如America/MontrealAfrica/CasablancaPacific/Auckland Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!). 切勿使用2-4字母的缩写,例如ESTIST因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

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

ZonedDateTime

To track moments, use the ZonedDateTime class. 要跟踪时刻,请使用ZonedDateTime类。 This class combines a date, a time-of-day, and a time zone. 此类组合了日期,一天中的时间和时区。

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

And the stop time. 和停止时间。

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

Calculate elapsed time using Duration class. 使用Duration类计算经过的时间。

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

ISO 8601 ISO 8601

I recommend you not report elapsed time using time-of-day format, HH:MM:SS. 我建议您不要使用时间格式HH:MM:SS报告经过时间。 Instead use the standard format defined for this purpose , in the ISO 8601 standard. 而是使用为此目的定义的标准格式 ,即ISO 8601标准。

So, 8.5 hours would be PT8H30M . 因此, PT8H30M 8.5小时。

The java.time classes use ISO 8601 formats by default when parsing/generating strings. 解析/生成字符串时, java.time类默认使用ISO 8601格式。

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

And parsing. 并解析。

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

About java.time 关于java.time

The java.time framework is built into Java 8 and later. java.time框架内置于Java 8及更高版本中。 These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat . 这些类取代了麻烦的旧的旧式日期时间类,例如java.util.DateCalendarSimpleDateFormat

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes. 现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial . 要了解更多信息,请参见Oracle教程 And search Stack Overflow for many examples and explanations. 并在Stack Overflow中搜索许多示例和说明。 Specification is JSR 310 . 规格为JSR 310

You may exchange java.time objects directly with your database. 您可以直接与数据库交换java.time对象。 Use a JDBC driver compliant with JDBC 4.2 or later. 使用与JDBC 4.2或更高版本兼容的JDBC驱动程序 No need for strings, no need for java.sql.* classes. 不需要字符串,不需要java.sql.*类。

Where to obtain the java.time classes? 在哪里获取java.time类?

The ThreeTen-Extra project extends java.time with additional classes. ThreeTen-Extra项目使用其他类扩展了java.time。 This project is a proving ground for possible future additions to java.time. 该项目为将来可能在java.time中添加内容提供了一个试验场。 You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more . 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

You can use the SimpleDateFormat for getting the input. 您可以使用SimpleDateFormat获取输入。 I'm using the predefined input, since you wanted the difference calculation between two given times. 我使用的是预定义的输入,因为您希望计算两个给定时间之间的差。 Here is the code fo you. 这是您的代码。 Please note I have given out the answer for both 24 or 12 hours format. 请注意,我给出了24或12小时格式的答案。

Getting the value of sleep time and waking up time 获得睡眠时间和唤醒时间的价值

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

For difference is less than zero, this happens in 12 hours format 因为差异小于零,所以以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());
}

Calculating the difference 计算差异

//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"); 

I hope it will answer your query. 希望它能回答您的查询。 Thanks :) 谢谢 :)

Just Try following line of code to get difference in minutes 只需尝试以下代码行,即可在几分钟内获得差异

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.
}

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

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