जावा में अवधि कैसे प्रारूपित करें? (उदाहरण स्वरूप H: MM: SS)


165

मैं एच: एमएम: एसएस जैसे पैटर्न का उपयोग करके सेकंड में एक अवधि प्रारूप करना चाहता हूं। जावा में वर्तमान उपयोगिताओं को एक समय प्रारूप करने के लिए डिज़ाइन किया गया है, लेकिन एक अवधि नहीं।

जवाबों:


84

यदि आप 8 से पहले जावा के एक संस्करण का उपयोग कर रहे हैं ... आप Joda Time और का उपयोग कर सकते हैं PeriodFormatter। यदि आपको वास्तव में एक अवधि मिल गई है (अर्थात एक कैलेंडर सिस्टम का कोई संदर्भ नहीं है), तो आपको संभवतः Durationसबसे अधिक भाग के लिए उपयोग करना चाहिए - तब आप कॉल कर सकते हैं toPeriod(जो PeriodTypeआप प्रतिबिंबित करना चाहते हैं कि क्या 25 घंटे बन जाते हैं) 1 दिन और 1 घंटा या नहीं, आदि) Periodजिसे आप प्रारूपित कर सकते हैं।

यदि आप जावा 8 या उसके बाद का उपयोग कर रहे हैं: मैं आमतौर java.time.Durationपर अवधि का प्रतिनिधित्व करने के लिए उपयोग करने का सुझाव देता हूं । आप तब कॉल कर सकते हैं getSeconds()या जब आप की जरूरत हो तो बोबर्स के उत्तर के अनुसार मानक स्ट्रिंग फॉर्मेटिंग के लिए एक पूर्णांक प्राप्त करना चाहते हैं - हालाँकि आपको उस स्थिति से सावधान रहना चाहिए जहाँ अवधि नकारात्मक है, जैसा कि आप शायद आउटपुट स्ट्रिंग में एक ही नकारात्मक चिन्ह चाहते हैं। । तो कुछ इस तरह:

public static String formatDuration(Duration duration) {
    long seconds = duration.getSeconds();
    long absSeconds = Math.abs(seconds);
    String positive = String.format(
        "%d:%02d:%02d",
        absSeconds / 3600,
        (absSeconds % 3600) / 60,
        absSeconds % 60);
    return seconds < 0 ? "-" + positive : positive;
}

इस तरह से स्वरूपण करना काफी सरल है, अगर गुस्सा मैन्युअल रूप से हो। के लिए पार्स करने में यह एक कठिन बात सामान्य रूप में हो जाता है ... तुम अब भी भी जावा 8 के साथ Joda समय का उपयोग करता है, तो आप निश्चित रूप से, करने के लिए चाहते हो सकता है।


क्या आप अभी भी जावा 8 का उपयोग करते समय जोडा टाइम लाइब्रेरी का उपयोग करने की सलाह देंगे?
टिम ब्यूटे

1
@ TimBüthe: नहीं, मैं उस मामले में java.time का उपयोग करना शुरू करूंगा। (हालांकि मैं तुरंत पीरियडफॉर्मर के बराबर नहीं पा सकता ...)
जॉन स्कीट

1
PeriodFormatter शामिल नहीं है। जावा 8 डेट टाइम एपीआई और जोडा टाइम के बीच अंतर।
टिम ब्यूटे

1
@RexKerr: यदि आप चाहते हैं, तो निश्चित रूप से, "जोडा टाइम का उपयोग करें" अभी भी है। फिर से संपादित करेंगे। (पीछे मुड़कर देखें, मुझे लगता है कि वैसे भी, अवधि की सिफारिश की जानी चाहिए थी। महत्वपूर्ण संपादन आवश्यक ...)
जॉन स्कीट

4
@MarkJeronimus भी आसान उपयोग करने के लिए किया जाएगा Durationरों तरीके: duration.toHours(), duration.toMinutesPart()और duration.toSecondsPart()जो जावा 9. के बाद से उपलब्ध हैं और प्राप्त करने के लिए निरपेक्ष मूल्य से एक का उपयोग कर सकते हैं duration.abs()
recke96

195

यदि आप पुस्तकालयों में नहीं खींचना चाहते हैं, तो यह आसान है कि आप अपने आप को फ़ॉर्मैटर, या संबंधित शॉर्टकट जैसे उदाहरण का उपयोग करें। सेकंड के पूर्णांक संख्या:

  String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60));

4
पूर्णांक होना आवश्यक नहीं है। यदि आपके पास दो तिथियां हैं, तो उपरोक्त समीकरण में सिर्फ date1.getTime () - date2.getTime () प्लग करें जो लंबे समय तक आदिम और अभी भी काम करता है।
जोश

क्या होगा यदि समय अंतर 24 घंटों से अधिक हो?
राजिष जू

2
@ रजीश: आपको ओपी से पूछना होगा कि वे उस मामले में क्या चाहते थे! बेशक, s/86400, (s%86400)/3600...यदि आवश्यक हो तो आप इसे दिनों के लिए अलग कर सकते हैं ...
बोबिन्स

मेरा समाधान s > 86400 (एक दिन): "\u221E"- अनंत
QED

यदि समय अंतर 24 घंटे से अधिक है, यह अभी भी घंटे, मिनट और सेकंड में अच्छी तरह से प्रारूपित करता है। मेरे उपयोग के मामले में यह उम्मीद के मुताबिक है।
ऑड्रीस मेसकॉस्कस

123

मैं अपाचे आम की अवधिफरमैट यूटिल्स का उपयोग करता हूं जैसे:

DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true);

13
सबसे आसान संभव तरीका (अपाचे कॉमन्स शैली में)। आपके पास प्रारूपधर्म विधि भी है, जिसका उपयोग आप शायद अधिकतर समय करेंगे।
मार्को

उत्तम! आप एपोस्ट्रोफ के भीतर अन्य पाठ भी जोड़ सकते हैं: DurationFormatUtils.formatDuration (
periodInMillis

29

जावा 9 के बाद से यह आसान है। एक Durationअभी भी योग्‍य नहीं है, लेकिन घंटे, मिनट और सेकंड प्राप्त करने के तरीके जोड़े जाते हैं, जो कार्य को कुछ अधिक सरल बनाता है:

    LocalDateTime start = LocalDateTime.of(2019, Month.JANUARY, 17, 15, 24, 12);
    LocalDateTime end = LocalDateTime.of(2019, Month.JANUARY, 18, 15, 43, 33);
    Duration diff = Duration.between(start, end);
    String hms = String.format("%d:%02d:%02d", 
                                diff.toHours(), 
                                diff.toMinutesPart(), 
                                diff.toSecondsPart());
    System.out.println(hms);

इस स्निपेट से आउटपुट है:

24:19:21


26
long duration = 4 * 60 * 60 * 1000;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault());
log.info("Duration: " + sdf.format(new Date(duration - TimeZone.getDefault().getRawOffset())));

14
हा! इस विधि का उपयोग करते समय बस समय क्षेत्र के सामान्यीकरण के साथ दीवार को मारो। फ़ंक्शन sdf.setTimeZone(TimeZone.getTimeZone("GMT+0"));का उपयोग करने से पहले आपको जोड़ना होगा format
राजिष जू

7

यह एक प्रकार का हैकी हो सकता है, लेकिन यह एक अच्छा समाधान है यदि कोई जावा 8 का उपयोग करके इसे पूरा करने पर तुला है java.time:

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.time.temporal.UnsupportedTemporalTypeException;

public class TemporalDuration implements TemporalAccessor {
    private static final Temporal BASE_TEMPORAL = LocalDateTime.of(0, 1, 1, 0, 0);

    private final Duration duration;
    private final Temporal temporal;

    public TemporalDuration(Duration duration) {
        this.duration = duration;
        this.temporal = duration.addTo(BASE_TEMPORAL);
    }

    @Override
    public boolean isSupported(TemporalField field) {
        if(!temporal.isSupported(field)) return false;
        long value = temporal.getLong(field)-BASE_TEMPORAL.getLong(field);
        return value!=0L;
    }

    @Override
    public long getLong(TemporalField field) {
        if(!isSupported(field)) throw new UnsupportedTemporalTypeException(new StringBuilder().append(field.toString()).toString());
        return temporal.getLong(field)-BASE_TEMPORAL.getLong(field);
    }

    public Duration getDuration() {
        return duration;
    }

    @Override
    public String toString() {
        return dtf.format(this);
    }

    private static final DateTimeFormatter dtf = new DateTimeFormatterBuilder()
            .optionalStart()//second
            .optionalStart()//minute
            .optionalStart()//hour
            .optionalStart()//day
            .optionalStart()//month
            .optionalStart()//year
            .appendValue(ChronoField.YEAR).appendLiteral(" Years ").optionalEnd()
            .appendValue(ChronoField.MONTH_OF_YEAR).appendLiteral(" Months ").optionalEnd()
            .appendValue(ChronoField.DAY_OF_MONTH).appendLiteral(" Days ").optionalEnd()
            .appendValue(ChronoField.HOUR_OF_DAY).appendLiteral(" Hours ").optionalEnd()
            .appendValue(ChronoField.MINUTE_OF_HOUR).appendLiteral(" Minutes ").optionalEnd()
            .appendValue(ChronoField.SECOND_OF_MINUTE).appendLiteral(" Seconds").optionalEnd()
            .toFormatter();

}

मैं सिर्फ यह कोशिश की, और मैंने देखा है कि अगर मैं "hh: mm: ss" के लिए प्रारूप कहा जाता है मैं जब फ्लॉप किसी भी घंटे या प्रारूप (जैसे करने के लिए मिनट है Duration.ofSeconds(20)), तो मैं एक मिल चाहते हैं UnsupportedTemporalTypeException)। अगर अंतर है तो मैंने बस कोड की जाँच को हटा दिया है == 01। मुझे लगा कि 01यह किसी प्रकार का मास्किंग मूल्य है जिसे मैं पूरी तरह नहीं समझता, क्या आप इसे समझा सकते हैं?
ग्रोस्तव १३'१५ को

यह वास्तव में बहुत अच्छा काम किया। मेरे मामले में मैंने मिलीसेकंड को भी जोड़ा ... isSupportedयदि मानव रीडिंग स्ट्रिंग पर दिखाने के लिए एक वैध क्षेत्र है तो इसकी जानकारी वापस करने की विधि के बारे में । वैसे भी "मास्किंग" वास्तव में एक मुखौटा नहीं है। कोड return value!=0lनहीं दिखाता है return value!=01। कृपया अगली बार कॉपी-पेस्ट का उपयोग करें।
श्रीजम्स ames

1
TemporalAccessorअवधि के लिए इंटरफ़ेस का दुरुपयोग नहीं होना चाहिए। JSR-310 ने TemporalAmountइस उद्देश्य के लिए इंटरफ़ेस तैयार किया है ।
Meno Hochschild

1
मेरा सुझाव है कि आप हमेशा Lएक longमूल्य को इंगित करने के लिए अपरकेस का उपयोग करें । lअंक 1 के लिए लोअरकेस को गलत तरीके से पढ़ाना इतना आसान है , जितना कि केवल दिखाया गया है।
ओले वीवी

6

यहाँ एक और नमूना है कि प्रारूप की अवधि कैसे तय करें। ध्यान दें कि यह नमूना सकारात्मक और नकारात्मक दोनों अवधि को सकारात्मक अवधि के रूप में दिखाता है।

import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.HOURS;
import static java.time.temporal.ChronoUnit.MINUTES;
import static java.time.temporal.ChronoUnit.SECONDS;

import java.time.Duration;

public class DurationSample {
    public static void main(String[] args) {
        //Let's say duration of 2days 3hours 12minutes and 46seconds
        Duration d = Duration.ZERO.plus(2, DAYS).plus(3, HOURS).plus(12, MINUTES).plus(46, SECONDS);

        //in case of negative duration
        if(d.isNegative()) d = d.negated();

        //format DAYS HOURS MINUTES SECONDS 
        System.out.printf("Total duration is %sdays %shrs %smin %ssec.\n", d.toDays(), d.toHours() % 24, d.toMinutes() % 60, d.getSeconds() % 60);

        //or format HOURS MINUTES SECONDS 
        System.out.printf("Or total duration is %shrs %smin %sec.\n", d.toHours(), d.toMinutes() % 60, d.getSeconds() % 60);

        //or format MINUTES SECONDS 
        System.out.printf("Or total duration is %smin %ssec.\n", d.toMinutes(), d.getSeconds() % 60);

        //or format SECONDS only 
        System.out.printf("Or total duration is %ssec.\n", d.getSeconds());
    }
}

5

यह उत्तर केवल Durationजावा 8 के तरीकों और कार्यों का उपयोग करता है:

public static String format(Duration d) {
    long days = d.toDays();
    d = d.minusDays(days);
    long hours = d.toHours();
    d = d.minusHours(hours);
    long minutes = d.toMinutes();
    d = d.minusMinutes(minutes);
    long seconds = d.getSeconds() ;
    return 
            (days ==  0?"":days+" jours,")+ 
            (hours == 0?"":hours+" heures,")+ 
            (minutes ==  0?"":minutes+" minutes,")+ 
            (seconds == 0?"":seconds+" secondes,");
}

4

निम्न फ़ंक्शन के बारे में कैसे, जो या तो + H: MM: SS या + H: MM: SS.sss देता है

public static String formatInterval(final long interval, boolean millisecs )
{
    final long hr = TimeUnit.MILLISECONDS.toHours(interval);
    final long min = TimeUnit.MILLISECONDS.toMinutes(interval) %60;
    final long sec = TimeUnit.MILLISECONDS.toSeconds(interval) %60;
    final long ms = TimeUnit.MILLISECONDS.toMillis(interval) %1000;
    if( millisecs ) {
        return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
    } else {
        return String.format("%02d:%02d:%02d", hr, min, sec );
    }
}

4

कम से कम 24 घंटे की अवधि के लिए कम से कम एक सरल और (IMO) सुरुचिपूर्ण दृष्टिकोण है:

DateTimeFormatter.ISO_LOCAL_TIME.format(value.addTo(LocalTime.of(0, 0)))

प्रारूपकों को प्रारूप के लिए एक अस्थायी वस्तु की आवश्यकता होती है, इसलिए आप 00:00 (यानी मध्यरात्रि) के स्थानीय समय की अवधि जोड़कर एक बना सकते हैं। यह आपको मध्यरात्रि से उस समय तक की अवधि का प्रतिनिधित्व करने वाला एक लोकल टाइम देगा, जो तब मानक एचएच: मिमी: एसएस नोटेशन में प्रारूपित करना आसान है। इसका लाभ बाहरी पुस्तकालय की आवश्यकता नहीं है, और यह मैन्युअल रूप से घंटे, मिनट और सेकंड की गणना करने के बजाय गणना करने के लिए java.time पुस्तकालय का उपयोग करता है।


3

यह काम करने का विकल्प है।

public static String showDuration(LocalTime otherTime){          
    DateTimeFormatter df = DateTimeFormatter.ISO_LOCAL_TIME;
    LocalTime now = LocalTime.now();
    System.out.println("now: " + now);
    System.out.println("otherTime: " + otherTime);
    System.out.println("otherTime: " + otherTime.format(df));

    Duration span = Duration.between(otherTime, now);
    LocalTime fTime = LocalTime.ofNanoOfDay(span.toNanos());
    String output = fTime.format(df);

    System.out.println(output);
    return output;
}

के साथ विधि को बुलाओ

System.out.println(showDuration(LocalTime.of(9, 30, 0, 0)));

कुछ इस तरह का उत्पादन करता है:

otherTime: 09:30
otherTime: 09:30:00
11:31:27.463
11:31:27.463

2
यह 23: 59: 59.999 से अधिक अवधि के लिए विफल हो जाएगा।
माइकल जंग

2
String duration(Temporal from, Temporal to) {
    final StringBuilder builder = new StringBuilder();
    for (ChronoUnit unit : new ChronoUnit[]{YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS}) {
        long amount = unit.between(from, to);
        if (amount == 0) {
            continue;
        }
        builder.append(' ')
                .append(amount)
                .append(' ')
                .append(unit.name().toLowerCase());
        from = from.plus(amount, unit);
    }
    return builder.toString().trim();
}

1

इस दुर्गंध का उपयोग करना

private static String strDuration(long duration) {
    int ms, s, m, h, d;
    double dec;
    double time = duration * 1.0;

    time = (time / 1000.0);
    dec = time % 1;
    time = time - dec;
    ms = (int)(dec * 1000);

    time = (time / 60.0);
    dec = time % 1;
    time = time - dec;
    s = (int)(dec * 60);

    time = (time / 60.0);
    dec = time % 1;
    time = time - dec;
    m = (int)(dec * 60);

    time = (time / 24.0);
    dec = time % 1;
    time = time - dec;
    h = (int)(dec * 24);
    
    d = (int)time;
    
    return (String.format("%d d - %02d:%02d:%02d.%03d", d, h, m, s, ms));
}

इस फंक्शन का पैकेज्ड वर्जन पाने के लिए github.com/ipserc/duration पर जाएं
ipserc

यह वह कोड था जिसकी मैं तलाश कर रहा था, स्वीकृत उत्तर बहुत अच्छा है, लेकिन इसमें उन दिनों की कमी है, जिनकी मुझे आवश्यकता थी
Filnor

0

मेरा पुस्तकालय Time4J एक पैटर्न-आधारित समाधान प्रदान करता है (समान Apache DurationFormatUtils, लेकिन अधिक लचीला):

Duration<ClockUnit> duration =
    Duration.of(-573421, ClockUnit.SECONDS) // input in seconds only
    .with(Duration.STD_CLOCK_PERIOD); // performs normalization to h:mm:ss-structure
String fs = Duration.formatter(ClockUnit.class, "+##h:mm:ss").format(duration);
System.out.println(fs); // output => -159:17:01

यह कोड घंटे के अतिप्रवाह और हस्ताक्षर को संभालने की क्षमताओं को प्रदर्शित करता है, पैटर्न के आधार पर अवधि-फ़ॉर्मेटर का एपीआई भी देखें ।


0

स्काला में (मैंने कुछ अन्य प्रयास देखे, और प्रभावित नहीं हुआ):

def formatDuration(duration: Duration): String = {
  import duration._ // get access to all the members ;)
  f"$toDaysPart $toHoursPart%02d:$toMinutesPart%02d:$toSecondsPart%02d:$toMillisPart%03d"
}

भयानक लगता है हाँ? इसलिए हम इस सामान को लिखने के लिए IDE का उपयोग करते हैं ताकि विधि कॉल ( $toHoursPartआदि) एक अलग रंग हो।

f"..."एक है printf/ String.formatशैली स्ट्रिंग क्षेपक (जो क्या अनुमति देता है $का उत्पादन को देखते हुए काम करने के लिए कोड इंजेक्शन) 1 14:06:32.583, fअंतर्वेशित स्ट्रिंग के बराबर होगाString.format("1 %02d:%02d:%02d.%03d", 14, 6, 32, 583)


-1

स्काला में, YourBestBet के समाधान पर निर्माण किया गया लेकिन सरलीकृत किया गया:

def prettyDuration(seconds: Long): List[String] = seconds match {
  case t if t < 60      => List(s"${t} seconds")
  case t if t < 3600    => s"${t / 60} minutes" :: prettyDuration(t % 60)
  case t if t < 3600*24 => s"${t / 3600} hours" :: prettyDuration(t % 3600)
  case t                => s"${t / (3600*24)} days" :: prettyDuration(t % (3600*24))
}

val dur = prettyDuration(12345).mkString(", ") // => 3 hours, 25 minutes, 45 seconds

-2

स्काला में, किसी पुस्तकालय की आवश्यकता नहीं है:

def prettyDuration(str:List[String],seconds:Long):List[String]={
  seconds match {
    case t if t < 60 => str:::List(s"${t} seconds")
    case t if (t >= 60 && t< 3600 ) => List(s"${t / 60} minutes"):::prettyDuration(str, t%60)
    case t if (t >= 3600 && t< 3600*24 ) => List(s"${t / 3600} hours"):::prettyDuration(str, t%3600)
    case t if (t>= 3600*24 ) => List(s"${t / (3600*24)} days"):::prettyDuration(str, t%(3600*24))
  }
}
val dur = prettyDuration(List.empty[String], 12345).mkString("")

3
यह स्काला के लिए एक बढ़िया विज्ञापन नहीं है? किसी लाइब्रेरी की जरूरत नहीं, लेकिन सिर्फ इतना कोड ...?
एडम

मुझे पुनरावर्ती दृष्टिकोण पसंद है, लेकिन इसे बहुत सरल किया जा सकता है: stackoverflow.com/a/52992235/3594403
dpoetzsch

-2

मैंने इसे नहीं देखा इसलिए मुझे लगा कि मैं इसे जोड़ूंगा:

Date started=new Date();
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
task
long duration=new Date().getTime()-started.getTime();
System.out.println(format.format(new Date(duration));

यह केवल 24 घंटों के लिए काम करता है लेकिन यही वह है जो मैं आमतौर पर अवधि के लिए चाहता हूं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.