0
\$\begingroup\$

I use this code to generate time until some date:

 String dateStop = "25/11/17 09:00:00";

    // Custom date format
    SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd HH:mm:ss");

    LocalDateTime d1 = LocalDateTime.now();
    Date d2 = null;
    try
    {
        d2 = format.parse(dateStop);
    }
    catch (ParseException e)
    {
        e.printStackTrace();
    }

    // Get msec from each, and subtract.
    long diff = d2.getTime() - d1.getTime();

    long days = TimeUnit.MILLISECONDS.toDays(diff);
    long remainingHoursInMillis = diff - TimeUnit.DAYS.toMillis(days);
    long hours = TimeUnit.MILLISECONDS.toHours(remainingHoursInMillis);
    long remainingMinutesInMillis = remainingHoursInMillis - TimeUnit.HOURS.toMillis(hours);
    long minutes = TimeUnit.MILLISECONDS.toMinutes(remainingMinutesInMillis);
    long remainingSecondsInMillis = remainingMinutesInMillis - TimeUnit.MINUTES.toMillis(minutes);
    long seconds = TimeUnit.MILLISECONDS.toSeconds(remainingSecondsInMillis);

    System.out.println("Days: " + days + ", hours: " + hours + ", minutes: " + minutes + ", seconds: " + seconds);

How I can get the same result but with much more less code?

\$\endgroup\$
  • \$\begingroup\$ Try figuring out how to convert the long 'diff' into another representation of time that meets your use case, instead of trying it manually. \$\endgroup\$ – Vivek Chavda Aug 7 '17 at 21:49
  • \$\begingroup\$ you don't have getTime() for LocalDateTime, your code is not working \$\endgroup\$ – azro Aug 7 '17 at 21:49
3
\$\begingroup\$

You do not need to use Date, parse, Exception, .... You only need LocalDateTime :

LocalDateTime d1 = LocalDateTime.now();
LocalDateTime d2 = LocalDateTime.parse("25/11/17 09:00:00", DateTimeFormatter.ofPattern("yy/MM/dd HH:mm:ss"));

long days = d1.until(d2, ChronoUnit.DAYS);
d1 = d1.plusDays(days);
long hours = d1.until(d2, ChronoUnit.HOURS);
d1 = d1.plusHours(hours);
long minutes = d1.until(d2, ChronoUnit.MINUTES);
d1 = d1.plusMinutes(minutes);
long seconds = d1.until(d2, ChronoUnit.SECONDS);

System.out.println(days + " days " + hours + " hours " + minutes + " minutes " + 
                                                         seconds + " seconds.");

Step by step, from large precision to small, it will look the difference with this precision and then add it to be nearer of the target

\$\endgroup\$
0
\$\begingroup\$

Inspired by azro's answer, I was motivated to squeeze every bit of code duplication out of it. This resulted in a design that is, ironically, even more verbose, but on the other hand allows for great flexibility in case you want to change the temporal units of the output (e.g., don't display seconds) or the type of the Temporals themselves (e.g. from LocalDateTime to ZonedDateTime):

public static <T extends Temporal> Map<TemporalUnit, Long> temporalDifference(T referenceTemporal, T otherTemporal, TemporalUnit... temporalUnits) {
    SortedSet<TemporalUnit> temporalUnitsSorted
            = Arrays
            .stream(temporalUnits)
            .collect(Collectors.toCollection(()
                    -> new TreeSet<>(
                            Comparator
                            .comparing(TemporalUnit::getDuration)
                            .reversed())));


    Map<TemporalUnit, Long> temporalUnitAmounts = new LinkedHashMap<>();
    T tempTemporal = referenceTemporal;
    for (TemporalUnit temporalUnit : temporalUnitsSorted) {
        long amountForThisUnit = temporalUnit.between(tempTemporal, otherTemporal);
        temporalUnitAmounts.put(temporalUnit, amountForThisUnit);
        tempTemporal.plus(amountForThisUnit, temporalUnit);
    }

    return temporalUnitAmounts;
}

And you can invoke it like this:

LocalDateTime d1 = LocalDateTime.now();
LocalDateTime d2 = LocalDateTime.parse("25/11/17 09:00:00", DateTimeFormatter.ofPattern("yy/MM/dd HH:mm:ss"));

Map<TemporalUnit, Long> temporalUnitAmounts
        = temporalDifference(
                d1,
                d2,
                ChronoUnit.DAYS,
                ChronoUnit.HOURS,
                ChronoUnit.MINUTES,
                ChronoUnit.SECONDS);

System.out.println("Days: " + temporalUnitAmounts.get(ChronoUnit.DAYS)
        + ", hours: " + temporalUnitAmounts.get(ChronoUnit.HOURS)
        + ", minutes: " + temporalUnitAmounts.get(ChronoUnit.MINUTES)
        + ", seconds: " + temporalUnitAmounts.get(ChronoUnit.SECONDS));
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.