Java时间计算

时间:2013-02-14 21:48:32

标签: java

所以我的方法收到24小时格式的时间(“HH:MM:SS”)并返回一个字符串差异时间。如果是当地时间下午2:00我应该能够“16:30:00”(下午4:30)发送它并输出“2小时30分钟”。但代码有一些问题,我只是一个初学者,我需要帮助来解决它。

问题是如果时间是下午4:40,我发送它“17:00:00”(下午5:00)它返回消息: 12小时20分钟而不是0小时20分钟。 另一个问题是,如果我发送当前时间,它将返回“12小时”,而不是像它应该的那样。

请记住,我只是java的初学者,数学真的不是我的事,所以任何帮助都非常感谢。感谢。

private static String timeUntil(String distanceTime) {
String returnMsg = null;
try {
    SimpleDateFormat sdfDate = new SimpleDateFormat("hh:mm:ss");
    Date now = new Date();
    java.text.DateFormat df = new java.text.SimpleDateFormat("hh:mm:ss");
    Date date1 = df.parse(sdfDate.format(now));
    Date date2 = df.parse(distanceTime);
    long diff = date2.getTime() - date1.getTime();
    int timeInSeconds = (int) (diff / 1000);
    int hours, minutes;

    hours = timeInSeconds / 3600;
    timeInSeconds = timeInSeconds - (hours * 3600);
    minutes = timeInSeconds / 60;

    if (hours >= 0) {
    returnMsg = hours + " hours" +
            "\n" + minutes + " mins";
    } else {
    returnMsg = minutes + " mins";
    }
} catch (Exception e) {
    e.printStackTrace();
}
return returnMsg;
}

5 个答案:

答案 0 :(得分:4)

在您的日期格式中,hh用于 12 - 小时。使用HH 24 -hour time:

new SimpleDateFormat("HH:mm:ss");

答案 1 :(得分:0)

代码审核评论......

  1. 不推荐使用大多数Date类的方法。您应该考虑使用Calendar(GregorianCalendar)而不是Date。

  2. 您的变量名称通常缺乏意义 - 您必须知道变量的目的才能知道其含义。如果使用更好的变量名,您的代码将更易于维护。 df可以重命名为“format”或“dateFormat”。

  3. 您创建一个Date对象'now',然后通过您的df DateFormat实例传递它,通过您的sdfDate实例,将其转换回Date。这是不必要的。将其替换为Date date1 = new Date();并删除Date now = new Date();。同时,我看到在单位之间进行转换时很难诊断出错误,因此您应该更改diff以表示它是毫秒,例如diff_ms。你应该保持名称一致 - 你从“不同”(diff)变为“timeInSeconds”。它们都应该是“timeInXxx”或“diff_xx”。 distanceTime参数应重命名为futureTime

  4. 你做了一堆数学来确定两次之间的差异,但有些库会为你做这件事。谷歌为“两个日期之间的java差异”找到了很多答案。

  5. 您的代码始终假定第二次出现在“now”之后。这应该包含在方法顶部的注释中。

  6. 当您实例化date1和date2时,它们可能都在同一天。尝试调试或至少在创建对象后立即将对象打印到stdout以查看是否是这种情况。这是你真正想要的吗?

  7. 您的代码无法处理闰年。

  8. 您为什么不寻找能够为您完成任务的图书馆,而不是自己处理所有的时间转换?

答案 2 :(得分:0)

这是您的固定代码。我已将日期格式更改为HH:mm:ss以及您的计算逻辑。试一试,告诉我们

private static String timeUntil(String distanceTime) {
    String returnMsg = null;
    try {
        SimpleDateFormat sdfDate = new SimpleDateFormat("HH:mm:ss");
        Date now = new Date();
        java.text.DateFormat df = new java.text.SimpleDateFormat("HH:mm:ss");
        Date date1 = df.parse(sdfDate.format(now));
        Date date2 = df.parse(distanceTime);
        long diff = date2.getTime() - date1.getTime();
        int timeInSeconds = (int) (diff / 1000);
        int hours, minutes;

        hours = timeInSeconds / 3600;
        timeInSeconds = timeInSeconds - (hours * 3600);
        minutes = timeInSeconds / 60;

        if (hours != 0) {
        returnMsg = hours + " hours" +
                "\n" + minutes + " mins";
        } else {
        returnMsg = minutes + " mins";
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return returnMsg;
    }

答案 3 :(得分:0)

这是一个更健壮并使用Java更现代的日期函数的示例。我可以一点一点地指出你可以在你的例子中做得更好的事情,但有时它更容易给你一个很好的例子,让你从其他人的代码中收集你所能做的好的风格。

import java.util.Calendar;

public class testSpace {
     public static void main (String ... args){
            System.out.println(timeUntil("00:12:12"));      
    }

    private static String timeUntil(String distanceTime){

        String[] times = distanceTime.split(":");

        Calendar now = Calendar.getInstance();

        Calendar then = Calendar.getInstance();
        then.set(Calendar.SECOND, Integer.parseInt(times[2]));
        then.set(Calendar.MINUTE, Integer.parseInt(times[1]));
        then.set(Calendar.HOUR, Integer.parseInt(times[0]) % 12);
        then.set(Calendar.AM_PM,  (Integer.parseInt(times[0]) >= 12 ) ? Calendar.PM : Calendar.AM);

        boolean isFuture = (then.getTimeInMillis() > now.getTimeInMillis());

        long interval = (isFuture)
            ? then.getTimeInMillis() - now.getTimeInMillis()
            : now.getTimeInMillis() - then.getTimeInMillis();

        return ((isFuture) ? "" : "-") + millToTime(interval);
    }

    public static long MILLISECOND_PER_HOUR = 1000*60*60;
    public static long MILLISECOND_PER_MIN = 1000*60;
    public static long MILLISECOND_PER_SECOND = 1000;

    public static String millToTime(long mill){
        long hours  = mill / MILLISECOND_PER_HOUR;
        long mins   = (mill % MILLISECOND_PER_HOUR) / MILLISECOND_PER_MIN;
        long sec    = ((mill % MILLISECOND_PER_HOUR) % MILLISECOND_PER_MIN) / MILLISECOND_PER_SECOND;
        return String.format("%d:%d:%d", hours, mins, sec);
    }
}

答案 4 :(得分:0)

TL;博士

仅适用于没有日期或时区的时间。

LocalTime start = LocalTime.of( "16:40" ) ;
LocalTime stop = LocalTime.of( "17:00" ) ;
Duration d = Duration.between( start , stop ) ;
  

PT20M

或者,对于区域中的日期时间。

ZoneId z = ZoneId.of( "America/Montreal" )
ZonedDateTime zdtNow = ZonedDateTime.now( z );
ZonedDateTime zdtThen = 
    ZonedDateTime.of(   // Pass a LocalDate, LocalTime, ZoneId.
        zdtNow.toLocalDate() ,  // Same date…
        LocalTime.parse( "16:30:00" ) ,  // … but different time-of-day.
        z  
    ) 
Duration d = Duration.between( zdtNow , zdtThen ) ;
  

PT2H30M

详细

您正在使用旧的日期时间类,现在是旧的,取而代之的是java.time类。

LocalTime

您错误地将日期时间类用于仅限时间的值。而是使用LocalTime类。并在计算经过时间时使用时间跨度类。

String input = "16:30:00" ;
LocalTime lt = LocalTime.parse( input );

Instant

Instant类代表UTC中时间轴上的一个时刻,分辨率为nanoseconds(小数部分最多九(9)位)。

Instant instant = Instant.now();

ZonedDateTime

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

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtNow = instant.atZone( z );  // Adjusted into your time zone.

现在为您指定的输入时间构建ZonedDateTime

ZonedDateTime zdtTarget = ZonedDateTime.of( zdtNow.toLocalDate() , lt , z );

Duration

使用Duration表示未附加到时间轴的已用时间。

Duration d = Duration.between( zdtNow , zdtTarget );

请注意,如果指定的时间早于当前时间,则持续时间将为负数。

持续时间

ISO 8601字符串

要获取描述该时间段的小时,分​​钟等的字符串,只需致电toString以生成PnYnMnDTnHnMnS格式P格式的字符串T标记开头,14:00:00将年 - 月 - 日与小时 - 分 - 秒分开。

如果同一区域中的当前时间为Duration,则输出为:

  

PT2H30M

Getter方法

奇怪的是,在Java 8中,这个类2缺少任何部分的getter方法,例如30等小时和toHoursPart分钟。 ISO 8601,例如toMinutesPartfrom pytz import timezone def get_curr_time(): pst = timezone('US/Pacific') cur_time = datetime.now(pst) return cur_time.strftime('%Y-%m-%d, %H:%M:%S')

关于java.time

Remedied in Java 9 with methods框架内置于Java 8及更高版本中。这些类取代了麻烦的旧java.time日期时间类,例如legacyjava.util.Date和& Calendar

现在位于SimpleDateFormatJoda-Time项目建议迁移到java.time。

要了解详情,请参阅maintenance mode。并搜索Stack Overflow以获取许多示例和解释。规范是Oracle Tutorial

从哪里获取java.time类?

  • JSR 310Java SE 8以及之后
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小功能和修复。
  • SE 9Java SE 6
    • 大部分java.time功能都被反向移植到Java 6& 7 {in SE 7
  • ThreeTen-Backport
    • Android项目专门为Android调整 ThreeTen-Backport (如上所述)。
    • 请参阅ThreeTenABP

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