簡體   English   中英

Java時間計算

[英]Java Time calculation

所以我的方法接收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小時”,而不是像它應該的那樣24。

請記住,我只是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;
}

在您的日期格式中, hh用於12小時。 使用HH 24小時:

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

代碼審查評論......

  1. 大多數Date類的方法都已棄用。 您應該考慮使用Calendar(GregorianCalendar)而不是Date。

  2. 您的變量名稱通常缺乏意義 - 您必須知道變量的目的才能知道其含義。 如果使用更好的變量名,您的代碼將更易於維護。 df可以重命名為“format”或“dateFormat”。

  3. 您現在創建一個Date對象,然后通過您的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. 而不是自己處理所有的時間轉換,為什么不尋找適合您的庫?

這是你的固定代碼。 我已將日期格式更改為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;
    }

這是一個更健壯的例子,並使用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);
    }
}

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時間軸上的一個時刻,分辨率為納秒 (最多九(9)位小數)。

Instant instant = Instant.now();

ZonedDateTime

確定掛鍾時間需要一個時區。 continent/region的格式指定適當的時區名稱 ,例如America/MontrealAfrica/CasablancaPacific/Auckland 切勿使用3-4字母縮寫,例如ESTIST因為它們不是真正的時區,不是標准化的,甚至不是唯一的(!)。

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以標准ISO 8601格式生成PnYnMnDTnHnMnS的字符串,其中P標記開頭, T將年 - 月 - 日與小時 - 分鍾分開-seconds。

如果同一區域的當前時間是14:00:00 ,則輸出為:

PT2H30M

吸氣方法

奇怪的是,在Java 8中,這個類Duration缺少任何部件的getter方法,例如2小時和30分鍾。 使用 toHoursParttoMinutesPart方法在Java 9中進行了 toMinutesPart


關於java.time

java.time框架內置於Java 8及更高版本中。 這些類取代了麻煩的舊遺留日期時間類,如java.util.DateCalendarSimpleDateFormat

現在處於維護模式Joda-Time項目建議遷移到java.time。

要了解更多信息,請參閱Oracle教程 並搜索Stack Overflow以獲取許多示例和解釋。 規范是JSR 310

從哪里獲取java.time類?

ThreeTen-Extra項目使用其他類擴展了java.time。 該項目是未來可能添加到java.time的試驗場。 您可以在這里找到一些有用的類,比如IntervalYearWeekYearQuarter ,和更多

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM