मैं जावा में "सुंदर प्रिंट" अवधि कैसे कर सकता हूं?


93

क्या किसी को जावा लाइब्रेरी के बारे में पता है जो बहुत सी मिलीसेकंड में एक संख्या को उसी तरह प्रिंट कर सकता है जो C # करता है?

जैसे, 123456 एमएस एक लंबे समय तक 4d1h3m5s के रूप में मुद्रित किया जाएगा।


1
FYI करें, आपके द्वारा वर्णित प्रारूप Durationसमझदार मानक में परिभाषित किया गया है, ISO 8601 : PnYnMnDTnHnMnSजहां P"पीरियड" का अर्थ है और शुरुआत को चिह्नित करता है, Tदिनांक भाग को समय भाग से अलग करता है, और बीच में एक एकल के साथ एक संख्या के वैकल्पिक रूप से होते हैं। -सूत्र का संक्षिप्त नाम। उदाहरण के लिए, PT4H30M= साढ़े चार घंटे।
बेसिल बोर्क

1
यदि बाकी सब विफल हो जाता है, तो यह स्वयं करना बहुत आसान मामला है। बस क्रमिक अनुप्रयोगों का उपयोग करें %और /संख्या को भागों में विभाजित करें। प्रस्तावित उत्तरों में से कुछ की तुलना में लगभग आसान है।
हॉट लिप्स

@HotLicks अधिक स्वच्छ और का उपयोग करने से साफ कोड के लिए पुस्तकालय तरीकों को छोड़ दें /और %
ओले वीवी

हां, जब मैंने यह प्रश्न (!) पूछा है, तब से 8 साल के अंतराल में मैंने जोडा के समय का उपयोग किया है, जो मेरे उपयोग के मामले को बहुत अच्छी तरह से
दर्शाता है

@phatmanace Joda-Time परियोजना अब रखरखाव-मोड में है, और जावा 8 और बाद में निर्मित java.time कक्षाओं में प्रवास की सलाह देती है ।
तुलसी Bourque

जवाबों:


91

पीरियडफॉरमैटरब्यूरी का उपयोग करके जोडा टाइम के लिए यह एक बहुत अच्छा तरीका है ।

तीव्र जीत: PeriodFormat.getDefault().print(duration.toPeriod());

जैसे

//import org.joda.time.format.PeriodFormatter;
//import org.joda.time.format.PeriodFormatterBuilder;
//import org.joda.time.Duration;

Duration duration = new Duration(123456); // in milliseconds
PeriodFormatter formatter = new PeriodFormatterBuilder()
     .appendDays()
     .appendSuffix("d")
     .appendHours()
     .appendSuffix("h")
     .appendMinutes()
     .appendSuffix("m")
     .appendSeconds()
     .appendSuffix("s")
     .toFormatter();
String formatted = formatter.print(duration.toPeriod());
System.out.println(formatted);

2
यह नीचे दिए गए उत्तर से प्रतीत होता है कि पीरियड का एक उदाहरण सीधे बनाया जा सकता है, पहले अवधि अवधि बनाए बिना और फिर इसे पीरियड्स में परिवर्तित करना। उदा। अवधि = नई अवधि (मिली); स्ट्रिंग स्वरूपित = formatter.print (अवधि);
बेसिल वांडेग्रिएंड

7
इस "period.toPeriod ()" रूपांतरण से सावधान रहें। यदि अवधि काफी बड़ी है, तो दिन का हिस्सा 0. के रूप में रहेगा। घंटे का हिस्सा बढ़ता रहेगा। आपको 25h10m23s मिलेंगे लेकिन कभी भी "d" नहीं मिलेगा। इसका कारण है कि जोडा के सख्त तरीकों में घंटों को दिनों में बदलने का कोई पूरी तरह से सही तरीका नहीं है। अधिकांश मामले, यदि आप दो उदाहरणों की तुलना कर रहे हैं और इसे प्रिंट करना चाहते हैं, तो आप नई अवधि (t1, t2) .toPeriod () के बजाय नई अवधि (t1, t2) कर सकते हैं।
बून

@ बून क्या आप जानते हैं कि अवधि को दिनों के संबंध में कैसे बदलना है? मैं उस अवधि का उपयोग करता हूं जिससे मैं अपने टाइमर पर दूसरे में स्थानापन्न कर सकता हूं। ईवेंट सेटिंग PeriodType.daysTime()या .standard()मदद नहीं की
12

4
@murt यदि आप वास्तव में चाहते हैं, और एक दिन की मानक परिभाषा को स्वीकार कर सकते हैं, तो आप ऊपर दिए गए कोड में "formatter.print (period.toPeriod ()। normalizedStandard ())" कर सकते हैं। मज़े करो!
बून

74

मैंने एक सरल समाधान बनाया है, जावा 8 Duration.toString()और रेगेक्स का थोड़ा सा उपयोग करके :

public static String humanReadableFormat(Duration duration) {
    return duration.toString()
            .substring(2)
            .replaceAll("(\\d[HMS])(?!$)", "$1 ")
            .toLowerCase();
}

परिणाम जैसा दिखेगा:

- 5h
- 7h 15m
- 6h 50m 15s
- 2h 5s
- 0.1s

यदि आप के बीच रिक्त स्थान नहीं चाहते हैं, तो बस निकालें replaceAll


6
आपको कभी भी toStrong () के आउटपुट पर निर्भर नहीं होना चाहिए क्योंकि यह आगे के संस्करणों में बदल सकता है।
वेल्टरटम्सचैफ

14
@Weltraumschaf इसे बदलने की संभावना नहीं है, क्योंकि यह javadoc में निर्दिष्ट है
aditsu ने छोड़ दिया क्योंकि SE EVIL

9
संभावना @Weltraumschaf के उत्पादन के रूप में परिवर्तित करने के लिए Duration::toStringअच्छी तरह से परिभाषित और अच्छी तरह से पहना के अनुसार स्वरूपित है आईएसओ 8601 मानक।
तुलसी बॉर्क

1
यदि आप अंश नहीं चाहते हैं, .replaceAll("\\.\\d+", "")तो कॉल करने से पहले जोड़ें toLowerCase()
zb226

1
@Weltraumschaf आम तौर पर आपकी बात सही है और मैं खुद अधिकांश कक्षाओं के आउटपुट () आउटपुट पर निर्भर नहीं होता। लेकिन इस बहुत विशिष्ट मामले में, विधि परिभाषा बताती है कि इसका आउटपुट ISO-8601 मानक का अनुसरण करता है, जैसा कि आप विधि के Javacoc में देख सकते हैं । इसलिए यह अधिकांश कक्षाओं की तरह कार्यान्वयन का विवरण नहीं है, इसलिए ऐसा कुछ नहीं है जो मैं एक भाषा की अपेक्षा
करूं

13

Apache commons-lang इसे उपयोगी बनाने के लिए एक उपयोगी वर्ग प्रदान करता है DurationFormatUtils

जैसे DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) ) => 4: 16: 02.000 (H: m: s.millis) DurationFormatUtils.formatDurationISO( 15362 * 1000 ) )=> P0Y0M0DT4H16M2.000S, cf. ISO8601


9

JodaTime में एक Periodवर्ग है जो इतनी मात्राओं का प्रतिनिधित्व कर सकता है, और ISO8601 प्रारूप IsoPeriodFormatमें ( जैसे ) प्रदान किया जा सकता है , उदाPT4D1H3M5S

Period period = new Period(millis);
String formatted = ISOPeriodFormat.standard().print(period);

यदि वह प्रारूप वह नहीं है जो आप चाहते हैं, तो PeriodFormatterBuilderआप अपने C # -स्टाइल सहित मनमाने लेआउट को इकट्ठा कर सकते हैं 4d1h3m5s


3
बस एक नोट के रूप में, डिफ़ॉल्ट रूप से new Period(millis).toString()उपयोग करता है ISOPeriodFormat.standard()
थॉमस ब्यूवैस

9

जावा 8 के साथ आप आईएसओ 8601 सेकंड आधारित प्रतिनिधित्व जैसे कि PT8H6M12.345S का उपयोग करके बाहरी पुस्तकालयों के बिना इसे प्रारूपित करने की toString()विधि का उपयोग कर सकते हैं ।java.time.Duration


4
ध्यान दें कि यह दिन प्रिंट नहीं करता है
विम देबलॉवे

58
सुनिश्चित नहीं हैं कि यह प्रारूप मेरे प्रिंट की परिभाषा को पूरा करता है । :-)
james.garriss

@ james.garriss इसे थोड़ा प्रीतिकर बनाने के लिए, erickdeoliveiraleal द्वारा उत्तर देखें ।
बेसिल बोर्के

7

यहां बताया गया है कि शुद्ध JDK कोड का उपयोग करके आप इसे कैसे कर सकते हैं:

import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;

long diffTime = 215081000L;
Duration duration = DatatypeFactory.newInstance().newDuration(diffTime);

System.out.printf("%02d:%02d:%02d", duration.getDays() * 24 + duration.getHours(), duration.getMinutes(), duration.getSeconds()); 

7

org.threeten.extra.AmountFormats.wordBased

ThreeTen-अतिरिक्त परियोजना है, जो स्टीफन Colebourne, JSR 310, के लेखक द्वारा बनाए रखा है java.time , और Joda समय , एक है AmountFormatsवर्ग जो मानक जावा 8 दिनांक समय वर्गों के साथ काम करता है। हालांकि, अधिक कॉम्पैक्ट आउटपुट के लिए कोई विकल्प नहीं है, यह काफी क्रियात्मक है।

Duration d = Duration.ofMinutes(1).plusSeconds(9).plusMillis(86);
System.out.println(AmountFormats.wordBased(d, Locale.getDefault()));

1 minute, 9 seconds and 86 milliseconds


2
वाह, जानकर अच्छा लगा, मैंने वह सुविधा नहीं देखी है। हालांकि एक बड़ा दोष है: ऑक्सफोर्ड कॉमा को मिस करना ।
बासिल बॉर्क

4
@BasilBourque ऑक्सफोर्ड कॉमा अमेरिका के लिए विशिष्ट है, लेकिन दिलचस्प रूप से ब्रिटेन के लिए नहीं। मेरा lib Time4J (जिसमें बेहतर अंतर्राष्ट्रीयकरण है) वर्ग net.time4j.PrettyTime में इस अंतर का समर्थन करता है और यदि वांछित है तो कॉम्पैक्ट आउटपुट पर नियंत्रण की भी अनुमति देता है।
मेनो होच्स्चिल्ड

6

जावा 9+

Duration d1 = Duration.ofDays(0);
        d1 = d1.plusHours(47);
        d1 = d1.plusMinutes(124);
        d1 = d1.plusSeconds(124);
System.out.println(String.format("%s d %sh %sm %ss", 
                d1.toDaysPart(), 
                d1.toHoursPart(), 
                d1.toMinutesPart(), 
                d1.toSecondsPart()));

2 डी 1 एच 6 एम 4 एस


आप "toHoursPart" और ऊपर कैसे प्राप्त कर रहे हैं?
घोटी और चिप्स

4

जोडा-टाइम के बिल्डर-एप्रोच का एक पैटर्न-आधारित समाधान होगा । यह मेरी लाइब्रेरी Time4J द्वारा पेश किया गया है । कक्षा की अवधि का उपयोग करके उदाहरण.फॉर्मेटर (अधिक पठनीयता के लिए कुछ स्थान जोड़े गए - रिक्त स्थान को हटाने से कामना सी # -स्टाइल का उत्पादन होगा:

IsoUnit unit = ClockUnit.MILLIS;
Duration<IsoUnit> dur = // normalized duration with multiple components
  Duration.of(123456, unit).with(Duration.STD_PERIOD);
Duration.Formatter<IsoUnit> f = // create formatter/parser with optional millis
  Duration.Formatter.ofPattern("D'd' h'h' m'm' s[.fff]'s'");

System.out.println(f.format(dur)); // output: 0d 0h 2m 3.456s

यह फ़ॉर्मेटर java.time-API की अवधि भी प्रिंट कर सकता है (हालाँकि, उस प्रकार की सामान्यीकरण विशेषताएँ कम शक्तिशाली हैं):

System.out.println(f.format(java.time.Duration.ofMillis(123456))); // output: 0d 0h 2m 3.456s

ओपी की उम्मीद है कि "123456 एमएस लंबे समय तक 4d1h3m5s के रूप में मुद्रित किया जाएगा" की गणना स्पष्ट रूप से गलत तरीके से की जाती है। मैं ढलान को कारण मानता हूं। ऊपर परिभाषित एक ही अवधि के फ़ॉर्मेटर का उपयोग पार्सर के रूप में भी किया जा सकता है। निम्न कोड दिखाता है कि "4d1h3m5s" इसके बजाय संगत है 349385000 = 1000 * (4 * 86400 + 1 * 3600 + 3 * 60 + 5):

System.out.println(
  f.parse("4d 1h 3m 5s")
   .toClockPeriodWithDaysAs24Hours()
   .with(unit.only())
   .getPartialAmount(unit)); // 349385000

एक अन्य तरीका वर्ग का उपयोग कर रहा है net.time4j.PrettyTime(जो कि स्थानीय उत्पादन और छपाई के सापेक्ष अच्छा है जैसे "कल", "अगले रविवार", "4 दिन पहले" आदि):

String s = PrettyTime.of(Locale.ENGLISH).print(dur, TextWidth.NARROW);
System.out.println(s); // output: 2m 3s 456ms

s = PrettyTime.of(Locale.ENGLISH).print(dur, TextWidth.WIDE);
System.out.println(s); // output: 2 minutes, 3 seconds, and 456 milliseconds

s = PrettyTime.of(Locale.UK).print(dur, TextWidth.WIDE);
System.out.println(s); // output: 2 minutes, 3 seconds and 456 milliseconds

यदि संक्षिप्ताक्षर उपयोग किए जाते हैं या नहीं, तो पाठ चौड़ाई नियंत्रित करती है। सूची प्रारूप को उपयुक्त स्थान चुनकर भी नियंत्रित किया जा सकता है। उदाहरण के लिए, मानक अंग्रेजी ऑक्सीफॉर्म कॉमा का उपयोग करता है, जबकि यूके नहीं करता है। Time4J का नवीनतम संस्करण v5.5 90 से अधिक भाषाओं का समर्थन करता है और CLDR-रिपॉजिटरी (एक उद्योग मानक) के आधार पर अनुवाद का उपयोग करता है।


2
यह सुंदर समय दूसरे उत्तर में एक से बेहतर है! बहुत बुरा मुझे यह पहले नहीं मिला।
ycomp

मुझे नहीं पता कि इस अच्छी तरह से काम कर रहे समाधान के लिए अब दो डाउनवोट क्यों हैं इसलिए मैंने उत्तर देने का फैसला किया है ताकि पार्सिंग (स्वरूपण के विपरीत) के बारे में और उदाहरण देकर ओपी की गलत उम्मीद को उजागर किया जा सके।
मेनो होच्स्चाइल्ड

4

User678573 के उत्तर पर आधारित एक जावा 8 संस्करण :

private static String humanReadableFormat(Duration duration) {
    return String.format("%s days and %sh %sm %ss", duration.toDays(),
            duration.toHours() - TimeUnit.DAYS.toHours(duration.toDays()),
            duration.toMinutes() - TimeUnit.HOURS.toMinutes(duration.toHours()),
            duration.getSeconds() - TimeUnit.MINUTES.toSeconds(duration.toMinutes()));
}

... चूँकि Java 8 में कोई PeriodFormatter नहीं है और getHours, getMinutes, जैसे कोई तरीके नहीं हैं ...

मुझे जावा 8 के लिए एक बेहतर संस्करण देखकर खुशी होगी।


फेंकता java.util.IllegalFormatConversionException: f! = java.lang.Long
erickdeoliveiraleal

अवधि d1 = Duration.ofDays (0) के साथ; d1 = d1.plusHours (47); d1 = d1.plusMinutes (124); d1 = d1.plusSeconds (124); System.out.println (String.format ("% s days and% sh% smf 1.0fs", d1.toDays (), d1.toHours () - TimeUnit.DAYS.toHours (d1.toDays ()), d1 .toMinutes () - TimeUnit.HOURS.toMinutes (d1.toHours ()), d1.toSeconds () - TimeUnit.MINUTES.toSeconds (d1 .toMinutes ())));
erickdeoliveiraleal

@erickdeoliveiraleal कि बाहर इशारा करने के लिए धन्यवाद। मुझे लगता है कि मैं मूल रूप से ग्रूवी के लिए कोड लिख रहा था, इसलिए यह उस भाषा में काम कर सकता था। मैंने इसे अब जावा के लिए सही किया।
टॉरस्टेन

3

मुझे लगता है कि यह आपके उपयोग के मामले में बिल्कुल फिट नहीं हो सकता है, लेकिन सुंदर समय यहां उपयोगी हो सकता है।

PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
//prints: “right now”

System.out.println(p.format(new Date(1000*60*10)));
//prints: “10 minutes from now”

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