How can I calculate a time span in Java and format

2019-01-02 21:11发布

I want to take two times (in seconds since epoch) and show the difference between the two in formats like:

  • 2 minutes
  • 1 hour, 15 minutes
  • 3 hours, 9 minutes
  • 1 minute ago
  • 1 hour, 2 minutes ago

How can I accomplish this??

17条回答
笑指拈花
2楼-- · 2019-01-02 21:21

I'm not an expert in Java, but you can do t1-t2=t3(in seconds) then divide that by 60, would give you minutes, by another 60 would give you seconds. Then it's just a matter of figuring out how many divisions you need.

Hope it helps.

查看更多
初与友歌
3楼-- · 2019-01-02 21:24

Since everyone shouts "YOODAA!!!" but noone posts a concrete example, here's my contribution.

You could also do this with Joda-Time. Use Period to represent a period. To format the period in the desired human representation, use PeriodFormatter which you can build by PeriodFormatterBuilder.

Here's a kickoff example:

DateTime myBirthDate = new DateTime(1978, 3, 26, 12, 35, 0, 0);
DateTime now = new DateTime();
Period period = new Period(myBirthDate, now);

PeriodFormatter formatter = new PeriodFormatterBuilder()
    .appendYears().appendSuffix(" year, ", " years, ")
    .appendMonths().appendSuffix(" month, ", " months, ")
    .appendWeeks().appendSuffix(" week, ", " weeks, ")
    .appendDays().appendSuffix(" day, ", " days, ")
    .appendHours().appendSuffix(" hour, ", " hours, ")
    .appendMinutes().appendSuffix(" minute, ", " minutes, ")
    .appendSeconds().appendSuffix(" second", " seconds")
    .printZeroNever()
    .toFormatter();

String elapsed = formatter.print(period);
System.out.println(elapsed + " ago");

Much more clear and concise, isn't it?

This prints by now

32 years, 1 month, 1 week, 5 days, 6 hours, 56 minutes, 24 seconds ago

(Cough, old, cough)

查看更多
何处买醉
4楼-- · 2019-01-02 21:26

Avoid legacy date-time classes

The other Answers may be correct but are outdated. The troublesome old date-time classes in Java are now legacy, supplanted by the java.time classes.

Likewise, the Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

Using java.time

Instant

two times (in seconds since epoch)

In java.time, we represent moments on the timeline in UTC as Instant. I will assume that your epoch is the same as that of java.time, the first moment of 1970 in UTC (1970-01-01T00:00:00Z). Note that an Instant has a resolution of nanoseconds. A convenience factory method constructs a Instant from whole seconds, as asked in the Question.

Instant start = Instant.ofEpochSecond( … );
Instant stop = Instant.ofEpochSecond( … );

Here we use the current moment and some minutes later.

Instant start = Instant.now() ;
Instant stop = start.plusSeconds( TimeUnit.MINUTES.toSeconds( 7L ) ) ;  // Seven minutes as a number of seconds.

Duration

In java.time, a span of time unattached to the timeline is represented in two ways. For years-month-days, we have Period. For hours-minutes-seconds, we have Duration.

Duration duration = Duration.between( start , stop );

Half-Open

The elapsed time is calculated with the Half-Open approach. In this approach, the beginning is inclusive while the ending is exclusive. This approach is commonly used in date-time work. I believe using this approach consistently across your code base will help to eliminate errors and misunderstandings due to ambiguities, and will ease the cognitive load of your programming.

ISO 8601

The ISO 8601 standard defines many practical formats for representing date-time values as text. These formats are designed to avoid ambiguity, be easy to parse by machine, and be intuitive to read by humans across cultures.

The java.time classes use these formats by default when parsing & generating strings.

For a span of time unattached to the timeline, the standard defines a format of PnYnMnDTnHnMnS where P marks the beginning and T separates any years-months-days from any hours-minutes-seconds. So an hour and a half is PT1H30M.

In our example code using seven minutes:

String outputStandard = duration.toString();

PT7M

See the above example code running live at IdeOne.com.

I suggest sticking with these formats whenever possible, certainly when exchanging or serializing date-time data, but also consider using in a user interface where appropriate and your users can be trained to use them.

I recommend never using the clock-hour format (ex: 01:30 for hour-and-a-half) as that format is completely ambiguous with a time-of-day.

Retrieving parts to build a String

If you must spell out the span of time as seen in the Question, you will need to build up the text yourself.

  • For Period, call getYears, getMonths, and getDays to retrieve each part.
  • Oddly, the Duration class lacked such getters in Java 8, but gained them in Java 9 and later: toDaysPart, toHoursPart, toMinutesPart, toSecondsPart, and toNanosPart.

Some example code, simple and basic to get you started.

int days = duration.toDaysPart() ;
int hours = duration.toHoursPart() ;
int minutes = duration.toMinutesPart() ;
int seconds = duration.toSecondsPart() ;
int nanos = duration.toNanosPart() ;

StringBuilder sb = new StringBuilder( 100 );

if( days != 0 ) { 
    sb.append( days + " days" ) ;
};

if( hours != 0 ) { 
    sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ;  // Append comma if any existing text.
    sb.append( hours + " hours" ) ;
};

if( minutes != 0 ) { 
    sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ;  // Append comma if any existing text.
    sb.append( minutes + " minutes" ) ;
};

if( seconds != 0 ) { 
    sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ;  // Append comma if any existing text.
    sb.append( seconds + " seconds" ) ;
};

if( nanos != 0 ) { 
    sb.append( ( sb.length = 0 ) ? ( "" ) : ( ", " ) ) ;  // Append comma if any existing text.
    sb.append( nanos + " nanos" ) ;
};

String output = sb.toString();

Or perhaps you could write slicker code using DateTimeFormatterBuilder in a manner shown with Joda-Time in the Answer by Balus C.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, andfz more.

查看更多
姐姐魅力值爆表
5楼-- · 2019-01-02 21:26

The Calendar class can handle most date related math. You will have to get the result of compareTo and output the format yourself though. There isn't a standard library that does exactly what you're looking for, though there might be a 3rd party library that does.

查看更多
人气声优
6楼-- · 2019-01-02 21:29

OK, after a brief peruse of the API it seems that you could do the following: -

  1. create some ReadableInstants representing start time and end time.
  2. Use Hours.hoursBetween to get the number of hours
  3. use Minutes.minutesBetween to get the number of minutes
  4. use mod 60 on the minutes to get the remaining minutes
  5. et voila!

HTH

查看更多
路过你的时光
7楼-- · 2019-01-02 21:30

The solution of "Abduliam Rehmanius" seems pretty nice, or you can use some above library or you can create new simple things, refer the JS solution at here: http://www.datejs.com/. It's not difficult to transform into Java lang :-)

Hope my link useful for you!

查看更多
登录 后发表回答