كيفية تنسيق المدة في جافا؟ (على سبيل المثال شكل H: MM: SS)

StackOverflow https://stackoverflow.com/questions/266825

  •  06-07-2019
  •  | 
  •  

سؤال

وأود أن تنسيق مدة في ثوان باستخدام نمط مثل H: MM: SS. تم تصميم المرافق الحالية في جافا لتنسيق الوقت ولكن ليس المدة.

هل كانت مفيدة؟

المحلول

إذا كنت تستخدم نسخة جافا قبل 8 ... يمكنك استخدام Joda الوقت PeriodFormatter . إذا كنت قد حصلت حقا مدة (أي مبلغ انقضى من الوقت، دون الإشارة إلى نظام التقويم) ثم يجب أن تكون على الأرجح باستخدام Duration بالنسبة للجزء الأكبر - يمكنك بعد ذلك دعوة toPeriod (تحديد كل ما PeriodType تريد تعكس سواء 25 ساعة تصبح 1 يوم و 1 ساعة أم لا، الخ) للحصول على Period التي يمكنك تنسيقها.

إذا كنت تستخدم جافا 8 أو أحدث: كنت تشير عادة باستخدام java.time.Duration لتمثيل المدة. ثم يمكنك استدعاء getSeconds() أو ما شابه ذلك للحصول على عدد صحيح لسلسلة القياسية تنسيق وفقا الجواب bobince إذا كنت بحاجة إلى - على الرغم من أنك يجب أن نكون حذرين من الحالة التي تكون فيها مدة سلبية، كما تريد على الارجح <م> واحدة علامة سلبية في سلسلة الانتاج. ذلك شيء من هذا القبيل:

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

وتنسيق بهذه الطريقة هو معقول بسيطة، إذا دليل مزعج. ل<م> تحليل يصبح الأمر أصعب بشكل عام ... هل يمكن الاستمرار في استخدام Joda الوقت حتى مع جافا 8 إذا كنت تريد، بطبيعة الحال.

نصائح أخرى

إذا كنت لا ترغب في سحب في المكتبات، انها بسيطة بما فيه الكفاية للقيام نفسك باستخدام المنسق، أو ذات الصلة الاختصار على سبيل المثال. نظرا عدد صحيح من ثواني ق:

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

ويمكنني استخدام أباتشي شيوعا في <لأ href = "http://commons.apache.org/proper/commons-lang/javadocs/api-3.0/org/apache/commons/lang3/time/DurationFormatUtils.html" يختلط = "noreferrer"> DurationFormatUtils مثل ذلك:

DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true);
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())));

وهذا سيكون من الأسهل مع جافا 9. Duration لا يزال لا formattable (ما أعرف)، ولكن يتم إضافة طرق للحصول على الساعات والدقائق والثواني، الأمر الذي يجعل مهمة إلى حد ما أكثر وضوحا:

        Duration diff = // ...;
        String hms = String.format("%d:%02d:%02d", 
                                   diff.toHoursPart(),
                                   diff.toMinutesPart(), 
                                   diff.toSecondsPart());

وهذا قد يكون نوع من hacky، وإنما هو حل جيد إذا كان أحد عازمة على تحقيق هذا java.time باستخدام جافا 8 في:

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

}

وهذه ستكون واحدة من الميزات الجديدة في جافا 7

JSR-310

وهنا هو واحد أكثر عينة كيفية تنسيق المدة. لاحظ أن هذه العينة تبين كلا مدة إيجابية وسلبية مدة إيجابية.

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

وهذا هو خيار العمل.

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

وماذا عن الدالة التالية، والتي ترجع إما + 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 );
    }
}
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();
}

وهذه الإجابة يستخدم فقط طرق 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,");
}

وهناك نهج بسيطة الى حد كبير و(IMO) أنيق، على الأقل لفترات أقل من 24 ساعة:

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

ومنسقات تحتاج كائن الزمني لشكل، حتى تتمكن من إنشاء واحد بإضافة المدة إلى LOCALTIME من 00:00 (أي منتصف الليل). هذا وسوف تعطيك LOCALTIME تمثل مدة من منتصف الليل وحتى ذلك الوقت، وهو بعد ذلك من السهل تهيئة في معيار HH: MM: SS التدوين. هذا له ميزة لا تحتاج مكتبة خارجية، ويستخدم المكتبة java.time للقيام الحساب، بدلا من احتساب الساعات والدقائق والثواني يدويا.

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

وهذا الرمز يدل على قدرات للتعامل مع ساعة الفائض وتوقيع المناولة، وانظر أيضا API، مدتها المنسق <لأ href = "http://time4j.net/javadoc-en/net/time4j/Duration.Formatter.html # ofPattern-java.lang.Class-java.lang.String- "يختلط =" نوفولو noreferrer "> بناء على نمط .

في سكالا، بناء على حل 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

وفي سكالا، أي مكتبة المطلوبة:

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("")

وأنا لم أر هذا واحد حتى ظننت فما استقاموا لكم فاستقيموا إضافته:

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 ساعة ولكن هذا ما أريد عادة لمدة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top