I need a different format of strings to convert to "DD.MM.YYYY".
"Thu, 3 Nov 2022 06:00:00 +0100" has to be changed to "03.11.2022"
and
"01.11.2022 20:00:00" to "01.11.2022".
All the formats are in String.
I tried doing
String pattern="DD.MM.YYYY";
DateTimeFormatter formatter=DateTimeFormatter.ofPattern(pattern);
new SimpleDateFormat(pattern).parse("01.11.2022 20:00:00")
I have also tried doing the following
java.time.LocalDateTime.parse(
item.getStartdatum(),
DateTimeFormatter.ofPattern( "DDMMYYYY" )
).format(
DateTimeFormatter.ofPattern("DD.MM.YYYY")
)
But got the error :
Exception in thread "main" java.time.format.DateTimeParseException:
Text 'Sun, 30 Oct 2022 00:30:00 +0200' could not be parsed at index 0
I tried doing the following as well
String pattern="DD.MM.YYYY";
DateFormat format = new SimpleDateFormat(pattern);
Date date = format.parse(01.11.2022 20:00:00);
However, I am not getting the correct output. How can I get my desired result?
Several things…
if you can use java.time, use it exclusively if possible (no SimpleDateFormat or similar legacy stuff)
a DateTimeFormatter can be used to parse and format Strings representing a datetime, if input and output format are different, you will need two different DateTimeFormatters
the Text 'Sun, 30 Oct 2022 00:30:00 +0200' could not be parsed at index 0 due to your try to parse it with the pattern "DD.MM.YYYY", which is wrong on several levels:
the pattern seems to expect the String to start with a numerical representation of the day of month, but it starts with Thu, an abbreviation of the name of a day of week
the symbol D means day of year, a number between 1 and 366 (in leap years, 365 otherwise)
the symbol Y means week-based year
Read more about those symbols in the JavaDocs of DateTimeFormatter
You could do the following instead:
public static void main(String[] args) {
// two example inputs
String first = "Thu, 3 Nov 2022 06:00:00 +0100";
String second = "01.11.2022 20:00:00";
// prepare a formatter for each pattern in order to parse the Strings
DateTimeFormatter dtfInFirst = DateTimeFormatter.ofPattern(
"EEE, d MMM uuuu HH:mm:ss x",
Locale.ENGLISH
);
// (second one does not have an offset from UTC, so the resulting class is different)
DateTimeFormatter dtfInSecond = DateTimeFormatter.ofPattern("dd.MM.uuuu HH:mm:ss");
// parse the Strings using the formatters
OffsetDateTime odt = OffsetDateTime.parse(first, dtfInFirst);
LocalDateTime ldt = LocalDateTime.parse(second, dtfInSecond);
// prepare a formatter, this time for output formatting
DateTimeFormatter dtfDateOnlySeparatedByDots = DateTimeFormatter.ofPattern("dd.MM.uuuu");
// extract the date part of each result of the parsing
LocalDate firstResult = odt.toLocalDate();
LocalDate secondResult = ldt.toLocalDate();
// and print it formatted using the output formatter
System.out.println(first + " ---> "
+ firstResult.format(dtfDateOnlySeparatedByDots));
System.out.println(second + " ---> "
+ secondResult.format(dtfDateOnlySeparatedByDots));
}
Which will output the conversion results as follows:
Thu, 3 Nov 2022 06:00:00 +0100 ---> 03.11.2022
01.11.2022 20:00:00 ---> 01.11.2022
The first formatter will need a Locale because of the presence of names (day of week & month). You cannot parse that using any exclusively numerical parser and the language / culture must match.<
short version
public static void main(String[] args) {
// two example inputs
String first = "Thu, 3 Nov 2022 06:00:00 +0100";
String second = "01.11.2022 20:00:00";
// prepare a custom formatter for the second pattern
DateTimeFormatter dtfInSecond = DateTimeFormatter
.ofPattern("dd.MM.uuuu HH:mm:ss");
// parse the first String by means of a built-in RFC formatter
OffsetDateTime odt = OffsetDateTime.parse(
first,
DateTimeFormatter.RFC_1123_DATE_TIME);
// parse the second String using the custom formatter
LocalDateTime ldt = LocalDateTime.parse(second, dtfInSecond);
// prepare a formatter, this time for output formatting
DateTimeFormatter dtfDateOnlySeparatedByDots = DateTimeFormatter
.ofPattern("dd.MM.uuuu");
// and print it formatted using the output formatter
System.out.println(first + " ---> "
+ odt.format(dtfDateOnlySeparatedByDots));
System.out.println(second + " ---> "
+ ldt.format(dtfDateOnlySeparatedByDots));
}
HINT:
For dates like the one mentioned in your comment…
Text '9.28.2022 6:30:00' could not be parsed at index 0
you will have to use a pattern with single-digit day of month and hour of day, probably even month of year if anything like 9.8.2022 is possible. However, you will definitely need to switch day of month and month of year because there is just no month no. 28 in a year.
Short example:
String third = "9.28.2022 6:30:00";
DateTimeFormatter dtfInThird = DateTimeFormatter
.ofPattern("M.d.uuuu H:mm:ss");
LocalDateTime ldtThird = LocalDateTime.parse(third, dtfInThird);
System.out.println(third + " ---> "
+ ldtThird.format(dtfDateOnlySeparatedByDots));
Executed in a main, this will output
9.28.2022 6:30:00 ---> 28.09.2022
The java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.
deHaar has already written a good answer. However, if you want to use a single DateTimeFormatter, you can check this answer.
For parsing, you can build a DateTimeFormatter with optional patterns and default time-zone offset value (since you do not have time-zone offset in the second date-time string) as follows:
DateTimeFormatter parser = new DateTimeFormatterBuilder()
.appendPattern("[d.M.uuuu H:m:s][EEE, d MMM uuuu H:m:s X]")
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter(Locale.ENGLISH);
where the optional patterns are in square brackets. Alternatively, you can use DateTimeFormatterBuilder#optionalStart and DateTimeFormatterBuilder#optionalEnd to specify optional patterns.
With this parser, you can parse the given date-time strings to OffsetDateTime and format it to the desired string using the following DateTimeFormatter:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.uuuu", Locale.ENGLISH);
Demo:
public class Main {
public static void main(String[] args) {
DateTimeFormatter parser = new DateTimeFormatterBuilder()
.appendPattern("[d.M.uuuu H:m:s][EEE, d MMM uuuu H:m:s X]")
.parseDefaulting(ChronoField.OFFSET_SECONDS, 0)
.toFormatter(Locale.ENGLISH);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.uuuu", Locale.ENGLISH);
// Test
Stream.of(
"Thu, 3 Nov 2022 06:00:00 +0100",
"01.11.2022 20:00:00"
)
.map(s -> OffsetDateTime.parse(s, parser).format(formatter).toString())
.forEach(System.out::println);
;
}
}
Output:
03.11.2022
01.11.2022
Note
Make sure to check the DateTimeFormatter documentation to understand the difference between Y and y and between D and d.
You can use y instead of u but I prefer u to y with DateTimeFormatter.
Learn more about the modern Date-Time API from Trail: Date Time.
Related
val dateStr = "2020 10 12 23 12 13"
val dateFormat = "yyyyMMddHHmmss"
import java.util.Date
val sdf = new SimpleDateFormat(dateFormat)
sdf.setLenient(false)
val res = sdf.parse(dateStr)
println("res = "+res)
scala> val res = sdf.parse(dateStr)
java.text.ParseException: Unparseable date: "2020 10 12 23 12 13"
at java.text.DateFormat.parse(DateFormat.java:366)
... 50 elided
The above code block parses and results in an exception, but if i change the "MM" part to "11" instead of "10" then it parses fine, without any exception , but with a wrong date. Any idea why is that ?
I want the code to fail or throw an exception if my date String is not in this format "yyyyMMddHHmmss"
/*Note the 11 instead of 10*/
val dateStr = "2020 11 12 23 12 13"
val dateFormat = "yyyyMMddHHmmss"
import java.util.Date
val sdf = new SimpleDateFormat(dateFormat)
sdf.setLenient(false)
val res = sdf.parse(dateStr)
println("res = "+res)
scala> val res = sdf.parse(dateStr)
res: java.util.Date = Wed Jan 01 01:02:23 PST 2020
SimpleDateFormat is simply too lenient for what you want.
It's parsing your date as:
2020 yyyy
_1 MM (where _ represents a space)
1 dd
_1 HH
2 mm
23 seconds
12 13 ignored
So I think the best way around it for you would be to bite the bullet and forbid spaces.
So try something like trimming the string and then searching for spaces in the middle. If you find spaces, throw an Exception.
But ultimately its probably better to drop SimpleDateFormat and use the new stuff. I think the new DateTimeFormatter class will serve you better:
// In Java
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
LocalDateTime date = LocalDateTime.parse(dateStr, formatter);
System.out.println("date="+date);
This throws and exception.
In Scala:
val formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
val date = LocalDateTime.parse(dateStr, formatter);
println("date="+date);
The Answer by Ruokki is correct, your formatting pattern does not match your input data.
java.time
More importantly, you are using the wrong classes. The date-time classes bundled with the earliest versions of Java are terrible. They were years ago supplanted by the modern java.time classes defined in JSR 310.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu MM dd HH mm ss" ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
To detect faulty inputs, trap for the DateTimeParseException.
try
{
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
}
catch ( DateTimeParseException e )
{
…
}
ResolverStyle
The DateTimeFormatter uses one of three different approaches in parsing: strict, smart and lenient. These are represented by the ResolverStyle enum. SMART is used by default, but you can specify STRICT if that better suits your needs.
ISO 8601
I suggest you educate the publisher of your input data about ISO 8601. That standard defines formats for exchanging date-time values textually.
The java.time classes use ISO 8601 formats by default when parsing/generating strings. So no need to define a formatting pattern for compliant inputs.
Hello I think the problem is the date format:
val dateFormat = "yyyyMMddHHmmss"
And should be
val dateFormat = "yyyy MM dd HH mm ss"
Because your dateStr contains some space who play a important part in the format
But if you want to fail in case you have space or other thing unwanted in the date maybe a regex is the best answer ?
I have two strings that I want to convert into a particular date time format so I can do a comparison. Problem I have is that it errors out in the parse with an exception and I wonder if I am doing something wrong. Wanted to ask what is the best way to convert two different string dates into a single date format
SimpleDateFormat localDateFormat = new SimpleDateFormat("yyyy dd mm - HH:mm:ss");
String firstDateString= "11 May 2018 21:03:51 GMT";
String secondDateString= "dataStore.get("2018-05-11T21:03:51Z";
Date firstDateFormat =localDateFormat.parse(firstDateString);
Date secondDateFormat =localDateFormat.parse(secondDateString);
Problem I have is that it errors out in the parse with an exception
and I wonder if I am doing something wrong.
=> Yes you are doing it actually. You first need to parse the date into it's actual format and then format it into the desired format.
For example: for parsing and formatting 2018-05-11T21:03:51Z
DateFormat originalFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:MM:SS'z'", Locale.ENGLISH);
DateFormat targetFormat = new SimpleDateFormat("yyyy dd mm - HH:mm:ss");
Date date = originalFormat.parse("2018-05-11T21:03:51Z");
String formattedDate = targetFormat.format(date); // 2018 05 11 - 21:03:51
Here:
SimpleDateFormat localDateFormat = new SimpleDateFormat("yyyy dd mm - HH:mm:ss");
That format says: 4 year digits SPACE 2 day digits SPACE 2 month digits DASH and so on.
Thing is: neither your string dates:
"11 May 2018 21:03:51 GMT"
"2018-05-11T21:03:51Z"
Look like that. The first one is rather "dd M yyy ..." (doesnt start with year), and the second one uses "-" not " " as separator for the initial date.
Answer: you have to use a pattern that really matches the expected date strings, see here for the specs. And note for example that you will need to use M to match "May", the lowercase m is about digits, not words!
And note: the second example is an ISO date, and the DateTimeFormatter already has pre-defined formatters for those! (so be careful about re-inventing the wheel)
java.time
DateTimeFormatter firstFormatteer
= DateTimeFormatter.ofPattern("d MMM uuuu H:mm:ss z", Locale.ENGLISH);
String firstDateString = "11 May 2018 21:03:51 GMT";
String secondDateString = "2018-05-11T21:03:51Z";
Instant firstInstant = firstFormatteer.parse(firstDateString, Instant::from);
Instant seoncdInstant = Instant.parse(secondDateString);
System.out.println("The strings are parsed into " + firstInstant + " and " + seoncdInstant);
Output is:
The strings are parsed into 2018-05-11T21:03:51Z and 2018-05-11T21:03:51Z
Your strings from two services are in two different formats, and the best you can do is to handle them in two different ways. For the first, define a formatter that matches the format. The second is in ISO 8601 format. Instant parses this format without any explicit formatter, so here we don’t need to define one.
To compare do for example:
if (firstInstant.isBefore(seoncdInstant)) {
System.out.println("The first date and time comes first");
} else if (firstInstant.equals(seoncdInstant)) {
System.out.println("The date and time is the same");
}
The date and time is the same
The Instant class is the modern replacement for the Date class, it represents a moment in time.
The Date class was poorly designed and SimpleDateFormat notoriously troublesome, fortunately they are both long outdated. I recommend you avoid them and use java.time, the modern Java date and time API, instead.
Link: Oracle tutorial: Date Time explaining how to use java.time.
This question already has answers here:
Change date format in a Java string
(22 answers)
how to parse output of new Date().toString()
(4 answers)
Closed 3 years ago.
I have a string "Mon Jan 01 00:00:00 AEDT 1990" and I need to convert it into the format "yyyyMMdd" so in this case it would be "19900101".
I think it's possible to do this with Regular Expressions so that I could pull out the year, month(but would need to convert Jan to 01 and etc) and day from the string but I am not well versed in Regular Expressions. Anyone have any ideas?
tl;dr
Regex is overkill.
Here is a one-liner solution using java.time classes built into Java.
ZonedDateTime // Represent a moment as seen through the wall-clock time used by the people of a certain region (a time zone).
.parse( // Parse the input text.
"Mon Jan 01 00:00:00 AEDT 1990" ,
DateTimeFormatter.ofPattern(
"EEE MMM dd HH:mm:ss z uuuu" , // Specify a custom formatting pattern to match our input.
Locale.US // Specify a `Locale` for the human language to use in translating the name of month& day-of-week.
) // Returns a `DateTimeFormatter` object.
) // Returns a `ZonedDateTime` object.
.toLocalDate() // Extract the date, without time-of-day and without time zone.
.format( // Generate text to represent the value of our `LocalDate` object.
DateTimeFormatter.BASIC_ISO_DATE // Use the predefined formatting pattern YYYYMMDD.
) // Returns a String.
19900101
java.time
Regex is overkill for this.
The modern approach uses java.time classes.
Specify a custom formatting pattern to fit your input.
Specify a locale to facilitate translating the name of day-of-week and name of month.
ZonedDateTime
Parse as a ZonedDateTime, a moment as seen through the wall-clock time used by the people of a specific region (a time zone).
String input = "Mon Jan 01 00:00:00 AEDT 1990";
Locale locale = Locale.US;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "EEE MMM dd HH:mm:ss z uuuu" , locale );
ZonedDateTime zdt = ZonedDateTime.parse( input , f );
System.out.println( "zdt: " + zdt );
zdt: 1990-01-01T00:00+11:00[Australia/Sydney]
By the way, your input string is in a terrible format. It uses the 2-4 character pseudo-zones that are not actual time zones, not standardized, and are not unique! Another problem is depending on English. And it is difficult to parse. Educate the people publishing your data about the beauty of the ISO 8601 standard, created for exchanging date-time values as text.
LocalDate
You want only the date. So extract a LocalDate.
LocalDate ld = zdt.toLocalDate() ; // Extract only the date, leaving behind the time-of-day and the time zone.
Your desired output format has already been defined in the DateTimeFormatter class. The standard ISO 8601 format for a date is YYYY-MM-DD. A variation of that is known as "Basic" meaning it minimizes the use of delimiters: YYYYMMDD.
String output = ld.format( DateTimeFormatter.BASIC_ISO_DATE ) ;
19900101
Check if something like this helps
//date string
String soTime = "Mon Jan 04 12:30:23 AEDT 1990";
//Format
SimpleDateFormat so = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy");
SimpleDateFormat desiredFormat = new SimpleDateFormat("yyyyMMdd");
desiredFormat.setTimeZone(TimeZone.getTimeZone("Australia/Sydney"));
Date sodate = so.parse(soTime);
System.out.println("DAY : " + desiredFormat.format(sodate));
Parse date with AEDT and AEST time zone in java
Now assuming that each month and day names inside each passed string is matching one of enum name values (i.e "Mar" matches the value of field name in Month.MARCH, while "Marc" or "March" do not) and the format of the sample string you gave us is truly consistent, as in it is no subject to change during runtime and will always remain <day-name> <month> <day> <time> <zone> <year> where year is always a 4 digit number, the following code should answer give you exactly what you want:
Main Class
public static void main(String[] args) {
String time = "Mon Jul 05 00:00:00 AEDT 1990";
int result = CustomDateFormat.parseToInt(time);
System.out.println("Parsed in format [yyyyMMdd]: " + result);
}
CustomDateFormat Class
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class CustomDateFormat {
private static final Pattern STANDARD_PATTERN =
Pattern.compile("^(?:[a-zA-Z]{3})\\s([a-zA-Z]{3})\\s([0-9]{2}).*([0-9]{4})");
/*
* This is just in case you want
* the name of the day as well
*/
public enum Day {
MONDAY("Mon", "Monday"),
TUESDAY("Tue", "Tuesday"),
WEDNESDAY("Wed", "Wednesday"),
THURSDAY("Thu", "Thursday"),
FRIDAY("Fri", "Friday"),
SATURDAY("Sat", "Saturday"),
SUNDAY("Sun", "Sunday");
final String shortName;
final String fullName;
Day(String name1, String name2) {
this.shortName = name1;
this.fullName = name2;
}
public static String getFullName(String alias) {
for (Day d : Day.values()) {
if (d.shortName.equals(alias))
return d.fullName;
}
return "";
}
}
public enum Month {
JANUARY("Jan", 1), FEBRUARY("Feb", 2),
MARCH("Mar", 3), APRIL("Apr", 4),
MAY("May", 5), JUNE("Jun", 6),
JULY("Jul", 7), AUGUST("Aug", 8),
SEPTEMBER("Sep", 9), OCTOBER("Oct", 10),
NOVEMBER("Nov", 11), DECEMBER("Dec", 12);
final String name;
final int value;
Month(String name, int value) {
this.name = name;
this.value = value;
}
public static int getMonth(String month) {
for (Month m : Month.values()) {
if (m.name.equals(month))
return m.value;
}
return 0;
}
}
public static int parseToInt(String date) {
System.out.println("Parsing date: " + date);
Matcher matcher = STANDARD_PATTERN.matcher(date);
if (matcher.find() && matcher.groupCount() == 3)
{
int month = Month.getMonth(matcher.group(1));
int day = Integer.valueOf(matcher.group(2));
int year = Integer.valueOf(matcher.group(3));
if (day == 0 || month == 0) {
throw new IllegalStateException("Unable to parse day or month from date " + date);
}
else return Integer.valueOf(year + "0" + month + "0" + day);
}
else throw new IllegalStateException("Unable to parse date " + date);
}
}
Output
Parsing date: Mon Jul 05 00:00:00 AEDT 1990
Parsed in format [yyyyMMdd]: 19900705
Let me know if this meets your requirements and if any other conditions need to be met or special case scenarios considered. It's a fairly simple implementation so it should take no time to adjust it to more specific needs.
EDIT: Fix some implementation mistakes, change sample string to a custom one and remove redundant output line.
I am retrieving a date/time from an external data source, this is returned in the following format "14:30 Sat 05 May" with no year.
I've been trying to parse this to a LocalDateTime unsuccessfully. The data returned does not return a year as it is an assumption that we are always operating in the current year.
//date to parse
String time = "14:30 Sat 05 May";
//specify date format matching above string
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm E d MMM YYYY") ;
//we do not have a year returned but i can make the assumption we use the current year
LocalDateTime formatDateTime = LocalDateTime.parse(time, formatter).withYear(2018);
The above code throws the following exception
Exception in thread "main" java.time.format.DateTimeParseException: Text '14:30 Sat 05 May' could not be parsed at index 16
Any help appreciated.
Default year
Specify a default year in your DateTimeFormatter, using the DateTimeFormatterBuilder class by calling parseDefaulting and specifying the year-field with ChronoField.YEAR.
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.appendPattern("HH:mm E d MMM")
.parseDefaulting(ChronoField.YEAR, 2018) // <------
.toFormatter(Locale.ENGLISH);
With this formatter instead of yours:
LocalDateTime.parse( "14:30 Sat 05 May" , formatter )
…I get:
2018-05-05T14:30
See that code run live at IdeOne.com.
Points to note:
Your format pattern string needs to match the parsed string end-to-end. So when your date-time string doesn’t have a year in it, don’t include YYYY in your format pattern.
In any case don’t use uppercase YYYY here. It’s for week-based year and only useful with week numbers. If your string had had a year in it, you should have used uuuu or lowercase yyyy.
Make it a habit to give explicit locale to your formatter so you know it also works on other computers, and on yours when one day you play with its settings.
LocalDateTime.parse() expects a String that represents a valid date, which the year part.
You cannot set the year after invoking this method in this way :
LocalDateTime.parse(time, formatter).withYear(2018);
The year has to be set before because otherwise parse() throws DateTimeParseException.
As a workaround you may concatenate the current year in the input.
Some additional notes:
the pattern you use and the input date in textual format don't match exactly.
You don't specify a Locale for the parsing operation.
It means that it will work according to the local where the JVM is run.
To ensure that it works in any case, you should specify the Locale.
So you could try something like :
//date to parse
String time = "14:30 Sat 05 May";
time += " " + LocalDate.now().getYear();
//specify date format matching above string
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm EEE dd MMM yyyy", Locale.US) ;
//we do not have a year returned but i can make the assumption we use the current year
LocalDateTime formatDateTime = LocalDateTime.parse(time, formatter);
I need to convert a String containing a date into a date object.
The String will be in the format "yyyy-mm-dd HH:mm:ss" and I want the "MM/dd/yyyy HH:mm:ss a " format as result.
String dateString = "2018-03-20 09:31:31";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss a",
Locale.ENGLISH);
LocalDate date = LocalDate.parse(dateString , formatter);
The code above is throwing an exception.
You have to use two Formatter, one to covert String to LocalDateTime and the other to format this date as you want :
From String to LocalDateTime :
String dateString = "2018-03-20 09:31:31";
LocalDateTime date = LocalDateTime.parse(
dateString,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH)
);
Now From LocalDateTime to String :
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"MM/dd/yyyy HH:mm:ss a", Locale.ENGLISH
);
String newDate = date.format(formatter);
System.out.println(newDate);// 03/20/2018 09:31:31 AM
Note : You have to use LocalDateTime instead of just LocalDate, your format contain both date and time, not just date, else you will get an error :
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: HourOfDay
That's a common error, based on the misconception that dates have formats - but they actually don't.
Date/time objects have only values, and those values - usually numerical - represent the concept of a date (a specific point in the calendar) and a time (a specific moment of the day).
If you have a String, then you don't actually have a date. You have a text (a sequence of characters) that represents a date. Note that all of the strings below are different (they have a different sequence of characters), but all represent the same date (the same values, the same point in the calendar):
2018-03-20 09:31:31
03/20/2018 9:31:31 AM (using USA's format: month/day/year)
Tuesday, March 20th 2018, 09:31:31 am
and many others...
What you want to do is to get one format (one String, one text representing a date) and transform it to another format (anoter String, another different sequence of characters that represents the same date).
In Java (and in many other languages - if not all - btw) you must do it in 2 steps:
convert the String to a date/time object (convert the text to the numerical values) - that's what the parse method does
convert the date/time object to another format (convert the numerical values to another text)
That said, when you call the parse method, you're trying to transform a String (a text, a sequence of characters) into a date/time object. This means that the DateTimeFormatter must have a pattern that matches the input.
The input is 2018-03-20 09:31:31, which is year-month-day hour:minute:second. And the formatter you used to parse it has the pattern MM/dd/yyyy HH:mm:ss a (month/day/year hour:minute:second am/pm).
You used the output pattern (the one that should be used in step 2) to parse the input. That's why you've got an exception: the formatter tried to parse a month with 2 digits followed by a / when the input actually contains a year with 4 digits followed by a -.
You must use a different DateTimeFormatter for each step, using the correct pattern for each case. YCF_L's answer has the code that does the job, I'd just like to add one little detail. The formatter used for the output (step 2) is:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
"MM/dd/yyyy HH:mm:ss a", Locale.ENGLISH
);
Note that HH is used for the hours. Take a look at the javadoc and you'll see that uppercase HH represents the hour-of-day fields (values from 0 to 23 - so 1 AM is printed as 01 and 1 PM is printed as 13).
But you're also printing the AM/PM field (the a in the pattern), so maybe what you need is actually the lowercase hh, which is the clock-hour-of-am-pm (values from 1 to 12) or even KK (hour-of-am-pm (values from 0 to 11)).
String dateString = "2018-03-20 09:31:31";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date date = formatter.parse(dateInString);
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
String reportDate = df.format(date );
} catch (ParseException e) {
e.printStackTrace();
}
You need to do a 2 steps conversion:
from your String date time in the wrong format to a (tempoary) LocalDateTime object.
if you still want to only extract the date (Year-Month-day) do a LocalDateTime.toLocalDate()
From this LocalDateTime object into the your String object in the right format
String dateString = "2018-03-20 09:31:31";
DateTimeFormatter formatterForWrongFormat = new DateTimeFormatterBuilder()
.append(DateTimeFormatter.ISO_LOCAL_DATE)
.appendLiteral(" ")
.append(DateTimeFormatter.ISO_LOCAL_TIME)
.toFormatter();
//1- from String(wrong format) into datetime object
LocalDateTime dateTime = LocalDateTime.parse(dateString , formatterForWrongFormat);
// 1.1 extract date object (Optional)
LocalDate myDate = dateTime.toLocalDate();
// 2- now from your LocalDateTime to the String in the RIGHT format
DateTimeFormatter formatterForRightFormat = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss a",
Locale.ENGLISH);
System.out.println("right format: "+dateTime.format(formatterForRightFormat));
you can test this code here
You can use the SimpleDateFormatter which is easier to implement and permit you to change the format of your date easily.
More here : What are the date formats available in SimpleDateFormat class?
Hope this will help you !