1
votes

Below is my code for formatting time

public class FormatTime {

    public static void main(String[] args) throws Exception {
        FormatTime ft = new FormatTime();
        System.out.println(ft.evaluate("12/01/2014 05:30:15 PM","MM/dd/yyyy hh:mm:ss aa", "yyyy-MM-dd HH:mm:ss"));  
    }

    public String evaluate(String time,String iFormat ,String f) throws ParseException {
        SimpleDateFormat format = new SimpleDateFormat(f);
        SimpleDateFormat inFormat = new SimpleDateFormat(iFormat);

        Date date=inFormat.parse(time);
        String fechaNueva = format.format(date);
        return fechaNueva;
    }

}

Out put of this program is as expected that it give 2014-12-01 17:30:15.
But when I replace hh to HH in iFormat (same as in outputformat) then it give output in 12 out format 2014-12-01 05:30:15
Same also happens if I convert both in lower case that is hh. Why does this type of inconsistency occur?

2
If you replace hh with HH in iFormat, then the time 05:30:15 is read as the 24-hours clock and the PM is ignored...beny23
@agarwal_achhnera does this help youAnkur Singhal
I'm not sure why this question was voted down. Perhaps the downvoter could explain his/her reasons?? The code has an error in it, sure, but that's the nature of questions on stackoverflow. An error leads to a question and our collective wisdom helps solve it. Per ardua ad astra. The question may have shown insufficient research effort (which is the case with all questions, or they would be solved before coming to stackoverflow), but it did not show no research effort. I am voting it up, as it is a useful, clear question.Breandán Dalton
FYI, the troublesome old date-time classes such as java.util.Date, java.util.Calendar, and java.text.SimpleDateFormat are now legacy, supplanted by the java.time classes built into Java 8 & Java 9. See Tutorial by Oracle.Basil Bourque

2 Answers

3
votes

I don't think it's inconsistent. When you evaluate the time using HH it will ignore the aa bit, as it's evaluating the input as a 24-hour time, and the aa bit makes no sense. However, when you run it with hh it will read 05:30:15 PM as "half five in the afternoon" and writing it will give 2014-12-01 17:30:15. Reading 05:30:15 PM as a 24-hour time, will read it as "half five in the morning", throwing the PM bit away.

When having both formats with hh, you're both reading and writing in 12 hour format. For at to make sense, you would need to add the aa bit to the output format as well.

I hope that answers your question in a way that makes sense :)

1
votes

tl;dr

LocalDateTime.parse(            // Parse as a date-time lacking time zone or offset-from-UTC.
    "12/01/2014 05:30:15 PM" ,  // Define a formatting pattern to match input. Case-sensitive formatting code. Use `h` lowercase for 12-hour clock, 0-12. Use uppercase `H` for 24-hour clock, 0-23.
    DateTimeFormatter.ofPattern( "MM/dd/uuuu hh:mm:ss a" , Locale.US )
).format(                       // Generate a String in specific format. Generally better to let java.time localize automatically.
    DateTimeFormatter.ofPattern( "MM/dd/uuuu hh:mm:ss a" , Locale.US )
)

java.time

The modern approach uses java.time classes that supplanted the troublesome old date-time classes.

Get the current moment in UTC. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant instant = Instant.now() ;

To see that same moment through the lens of a wall-clock time used by people of a certain region (time zone), apply a ZoneId to get a ZonedDateTime.

Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

To generate a string in standard ISO 8601 format on any of these, call toString. The java.time classes use standard formats by default when paring/generating strings. So no need to specify a formatting pattern.

If you want other formats, use the DateTimeFormatter or DateTimeFormatterBuilder classes. You can specify a formatting pattern, but easier to let java.time automatically localize.

To localize, specify:

  • FormatStyle to determine how long or abbreviated should the string be.
  • Locale to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.

Example:

Locale l = Locale.FRENCH ; 
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( l );
String output = zdt.format( f );

mercredi 14 février 2018 à 00:59:07 heure normale d’Europe centrale

Or, Locale.US & FormatStyle.SHORT.

2/14/18, 1:01 AM

Your custom format for your input is:

String input = "12/01/2014 05:30:15 PM" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu hh:mm:ss a" , Locale.US ) ;

That input string lacks any indicator of a time zone or offset-from-UTC. So it is not a moment, not a specific point on the timeline. It represents a vague idea about potential moments along a range of about 26-27 hours. As such, we parse this input into a LocalDateTime lacking any concept of zone/offset.

LocalDateTime ldt = LocalDateTime.parse( input , f ) ;

ldt.toString(): 2014-12-01T17:30:15

Generate a string in that format.

String output = ldt.format( f ) ;

12/01/2014 05:30:15 PM

As others explained, the formatting codes are case-sensitive. If you want 24-hour time, use uppercase H. For 12-hour time, use lowercase h.

Note that the formatting codes in java.time are close to those of the legacy SimpleDateFormat but not exactly the same. Study the documentation and search Stack Overflow for many examples.

When exchanging date-time values as text, stick with the standard ISO 8601 formats.

Table of date-time types in Java, both modern and legacy.


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.

Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.

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, and more.