Unable to parse DateTime-string with AM/PM marker - java

The string I want to format looks like this:
String datetime = "9/1/10 11:34:35 AM"
Following pattern for SimpleDateFormat works:
SimpleDateFormat sdf = SimpleDateFormat("M/d/yy h:mm:ss");
Date d = sdf.parse(datetime);
System.out.println(d);
Output> [Wed Sep 01 11:34:35 CEST 2010]
However I need to parse the AM/PM marker as well, and when I add that to the pattern I receive an exception.
Pattern that doesn't work:
SimpleDateFormat sdf = SimpleDateFormat("M/d/yy h:mm:ss a");
I have tried with this also with same exception:
SimpleDateFormat sdf = SimpleDateFormat("M/d/yy h:mm:ss aa");
Exception:
java.text.ParseException: Unparseable date: "9/1/10 11:34:35 AM"
I have looked through the API at http://download.oracle.com/javase/1.4.2/docs/api/java/text/SimpleDateFormat.html#text but canät seem to find where I do wrong.
Any suggestions?

One possibility is that your default Locale has different symbols for AM/PM. When constructing a date format you should always supply a Locale unless you really want to use the system's default Locale, e.g.:
SimpleDateFormat sdf = new SimpleDateFormat("M/d/yy h:mm:ss a", Locale.US)

Modern answer:
String datetime = "9/1/10 11:34:35 AM";
LocalDateTime dt = LocalDateTime.parse(datetime,
DateTimeFormatter.ofPattern("M/d/yy h:mm:ss a", Locale.ENGLISH));
This produces a LocalDateTime of 2010-09-01T11:34:35. Beware of two digit years, though; DateTimeFormatter will assume 2000 through 2099. For my birthday this would have been incorrect.
We still need to provide the locale. Since AM/PM markers are hardly used in practice in other locales than English, I considered Locale.ENGLISH a fairly safe bet. Please substitute your own.
The other answers were fine answers in 2010 and 2011. Already in 2014 the above was valid and I would have preferred it.

I am taking an example of date given below and print the formatted date into 24-hour format if suits your requirement.
String inputdate="9/1/10 11:34:35 AM";
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("dd/MM/yy hh:mm:ss aa",Locale.getDefault());
try {
System.out.println(""+new SimpleDateFormat("dd/MM/yy HH:mm:ss",Locale.getDefault()).format(simpleDateFormat.parse(inputdate)));
} catch (ParseException e) {
e.printStackTrace();
}
If you still have any query, Please respond. Thanks.

java.time
You can build a case-insensitive parser using DateTimeFormatterBuilder. Since a date-time parsing/formatting type (e.g. DateTimeFormatter, SimpleDateFormat etc.) is Locale-sensitive, you should always use a Locale with such a type. I've used Locale.ENGLISH because your date-time string has AM/PM marker in English.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;
import java.util.stream.Stream;
public class Main {
public static void main(String args[]) {
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("M/d/uu H:m:s a")
.toFormatter(Locale.ENGLISH);
//Test
Stream.of(
"9/1/10 11:34:35 AM",
"9/1/10 11:34:35 am",
"09/1/10 11:34:35 AM",
"9/01/10 11:34:35 Am"
).forEach(s -> System.out.println(LocalDateTime.parse(s, dtf)));;
}
}
Output:
2010-09-01T11:34:35
2010-09-01T11:34:35
2010-09-01T11:34:35
2010-09-01T11:34:35
Learn more about the the modern date-time API* from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

If you are working with FreeMarker for Java and pop on this issue use below code. I had this problem, my locale set AM/PM as DE. Not sure why...
<#setting locale="en_US">

Just a note about Locale:
the symbols used for AM/PM depend on Locale!
This affects parsing strings, eventually causing errors if the used AM/PM field does not match the predefined symbols. (obviously also affects formatting)
java.time.format.DateTimeFormatter and java.text.SimpleDateFormat accept an optional Locale when being created. If none is given. the systems default one is used.
Warning: using DateTimeFormatter the case of the AM/PM flag is also relevant when parsing, at least for some locales.
As an example, the Indian Locale requires the AM/PM flag being lowercase (am, pm), while some other locales (ROOT, ITALY, US, GERMANY) only accept uppercase AM/PM.
This throws DateTimeParseException: Text '2021-03-31 10:15:30 AM +05:30' could not be parsed at index 20
ZonedDateTime.parse("2021-03-31 10:15:30 AM +05:30",
DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss a Z",
new Locale("en", "IN")))
This results in 2021-03-31T10:15:30+05:30
ZonedDateTime.parse("2021-03-31 10:15:30 am +05:30",
DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss a Z",
new Locale("en", "IN")))
Using Locale.US, Locale.GERMANY or Locale.ROOT, the results are inverted.
Note: case of AM/PM does not matter when parsing with SimpleDateFormat (I am not recommending its use, I prefer DateTimeFormatter)

Related

How to resolve Unparseable date Exception in Java 8 with Date format yyyy-MM-dd hh:mm a

I have a text file from which I am reading and setting transaction POJO class data, to get the difference between start and end time I need to parse the time information in date object.
DateFormat format = new SimpleDateFormat(dateFormat);
System.out.println("Date format in play:"+dateFormat);
Transaction transaction = storageRepositroy.getTransaction(key);
Date start = format.parse(transaction.getStartDate() + " " + transaction.getStartTime());//line no. 29
Date end = format.parse(transaction.getEndDate() + " " + transaction.getEndTime());
I am getting exception while running this code
Exception is
Date format in play:yyyy-MM-dd hh:mm a
java.text.ParseException: Unparseable date: "2020–03–01 03:15 PM"
at java.text.DateFormat.parse(DateFormat.java:366)
at dc.tech.transaction.util.TimeUtil.calculateAverageTime(TimeUtil.java:29)
yyyy-MM-dd hh:mm a is the date format which I am passing to SimleDateFormat constructor. I am unable to understand and debug why I am getting this error.
java.time
I recommend that you use java.time, the modern Java date and time API, for your date and time work.
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuuu\u2013MM\u2013dd");
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("hh:mm a", Locale.ENGLISH);
String dateString = "2020–03–01";
String timeString = "03:15 PM";
LocalDate date = LocalDate.parse(dateString, dateFormatter);
LocalTime time = LocalTime.parse(timeString, timeFormatter);
LocalDateTime dateTime = date.atTime(time);
System.out.println(dateTime);
Output:
2020-03-01T15:15
With java.time it is straightforward to combine date and time after parsing, so I prefer to parse them individually.
What went wrong in your code?
Credits go to Ajeetkumar for noticing and reporting in comments: The hyphen in your date string is not a usual minus sign or hyphen with character value 2D hexadecimal (45 decimal), but a en dash with character value 2013 hexadecimal (8211 decimal). So when you specify a usual hyphen in your format pattern string, they don’t match, and parsing fails. Instead I am using a Unicode escape for putting the en dash into the format pattern string. Simply pasting it in there would have worked too (provided that you save your .java file with a character encoding that supports it), but I wanted to make the reader aware that something special was going on here, so I preferred the Unicode escape with \u.
There is another problem with your code: You are not providing any locale for your formatter. So it uses the default locale of your JVM. As long as that locale expects PM, parsing will work. If one day you change your locale setting or run your code on a computer or JVM with a different default locale, parsing will suddenly fail, at you may have a hard time figuring out why. I have specified English locale for parsing the time. Some would prefer doing it for the date too even though technically it isn’t necessary.
Links
Oracle tutorial: Date Time explaining how to use java.time.
Unicode Character 'EN DASH' (U+2013) on FileFormat.info.
I always stick to this mantra: use exactly the same format as your date-time string.
In the solutions given below, I have copied your date-time string into the pattern that I've specified for SimpleDateFormat and DateTimeFormatter and replaced the numbers with the corresponding letters e.g. 2020 with yyyy while keeping the rest of things (symbols, space etc.) intact.
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) throws ParseException {
DateFormat sdf = new SimpleDateFormat("yyyy–MM–dd hh:mm a", Locale.ENGLISH);// Make sure to use Locale
String dateTimeString = "2020–03–01 03:15 PM";// The string copied from the exception you have got
Date date = sdf.parse(dateTimeString);
System.out.println(sdf.format(date));
}
}
Output:
2020–03–01 03:15 PM
Note: The date-time API of java.util and their formatting API, SimpleDateFormat are outdated and error-prone. I suggest you should stop using them completely and switch to the modern date-time API.
Using the modern date-time API:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy–MM–dd hh:mm a", Locale.ENGLISH);// Make sure to use Locale
String dateTimeString = "2020–03–01 03:15 PM";// The string copied from the exception you have got
System.out.println(LocalDateTime.parse(dateTimeString, dtf));
}
}
Output:
2020-03-01T15:15
Learn more about the modern date-time API at Trail: Date Time.
If you are doing it for your Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Simpledateformat unparseable date

I have a String in a database (match.getDate) that has the following date format:
01/04/2018
This is the date I want to format, stored as day/month/year. I want to format this for my Android app.
I want to format the date into:
Sun 01 Apr 2018
My code below:
SimpleDateFormat fDate = new SimpleDateFormat("dd/MM/yyyy");
try {
textViewDate.setText(fDate.parse(match.getDate()).toString());
} catch (ParseException ex) {
System.out.println(ex.toString());
}
This outputs:
Sun Apr 08 00:00:00 GMT+00:00 2018.
I have also tried "EE, MM d, yyyy", but it gives me:
java.text.ParseException: Unparseable date: "01/04/2018"
The other answers solved your problem, but I think it's important to know some concepts and why your first attempt didn't work.
There's a difference between a date and a text that represents a date.
Example: today's date is March 9th 2018. That date is just a concept, an idea of "a specific point in our calendar system".
The same date, though, can be represented in many formats. It can be "graphical", in the form of a circle around a number in a piece of paper with lots of other numbers in some specific order, or it can be in plain text, such as:
09/03/2018 (day/month/year)
03/09/2018 (monty/day/year)
2018-03-09 (ISO8601 format)
March, 9th 2018
9 de março de 2018 (in Portuguese)
2018年3月5日 (in Japanese)
and so on...
Note that the text representations are different, but all of them represent the same date (the same value).
With that in mind, let's see how Java works with these concepts.
a text is represented by a String. This class contains a sequence of characters, nothing more. These characters can represent anything; in this case, it's a date
a date was initially represented by java.util.Date, and then by java.util.Calendar, but those classes are full of problems and you should avoid them if possible. Today we have a better API for that.
In Android, you can use the java.time classes if available in the API level you're using, or the threeten backport for API levels lower than that (check here how to use it). You'll have easier and more reliable tools to deal with dates.
In your case, you have a String (a text representing a date) and you want to convert it to another format. You must do it in 2 steps:
convert the String to some date-type (transform the text to numerical day/month/year values) - that's called parsing
convert this date-type value to some format (transform the numerical values to text in a specific format) - that's called formatting
Why your attempts didn't work:
the first attempt gave you the wrong format because you called Date::toString() method, which produces an output (a text representation) in that format (Sun Apr 08 00:00:00 GMT+00:00 2018) - so the parsing was correct, but the formatting wasn't
in the second attempt, you used the output pattern (EE dd MMM yyyy, the one you should use for formatting) to parse the date (which caused the ParseException).
For step 1, you can use a LocalDate, a type that represents a date (day, month and year, without hours and without timezone), because that's what your input is:
String input = "01/04/2018";
DateTimeFormatter inputParser = DateTimeFormatter.ofPattern("dd/MM/yyyy");
// parse the input
LocalDate date = LocalDate.parse(input, inputParser);
That's more reliable than SimpleDateFormat because it solves lots of strange bugs and problems of the old API.
Now that we have our LocalDate object, we can do step 2:
// convert to another format
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EE dd MMM yyyy", Locale.ENGLISH);
String output = date.format(formatter);
Note that I used a java.util.Locale. That's because the output you want has the day of week and month name in English, and if you don't specify a locale, it'll use the JVM's default (and who guarantees it'll always be English? it's better to tell the API which language you're using instead of relying on the default configs, because those can be changed anytime, even by other applications running in the same JVM).
And how do I know which letters must be used in DateTimeFormatter? Well, I've just read the javadoc.
Use this date formatter method I have created
public static String dateFormater(String dateFromJSON, String expectedFormat, String oldFormat) {
SimpleDateFormat dateFormat = new SimpleDateFormat(oldFormat);
Date date = null;
String convertedDate = null;
try {
date = dateFormat.parse(dateFromJSON);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(expectedFormat);
convertedDate = simpleDateFormat.format(date);
} catch (Exception e) {
e.printStackTrace();
}
return convertedDate;
}
and call this method like
dateFormater(" 01/04/2018" , "EE dd MMM yyyy" , "dd/MM/yyyy")
and you will get the desired output
You need two date formatters here. One to parse the input, and a different formatter to format the output.
SimpleDateFormat inDateFmt = new SimpleDateFormat("dd/MM/yyyy");
SimpleDateFormat outDateFmt = new SimpleDateFormat("EEE dd MMM yyyy");
try {
Date date = inDateFmt.parse(match.getDate());
textViewDate.setText(outDateFmt.format(date));
} catch (ParseException ex) {
System.out.println(ex.toString());
}
Try this, you can create any date format you want with this
public String parseTime(String date){
SimpleDateFormat format = new SimpleDateFormat("yyyy-dd-MM HH:mm:ss");
try {
Date date1 = format.parse(date.replace("T"," "));
String d= new SimpleDateFormat("yyyy/dd/MM HH:mm:ss").format(date1);
return d;
}catch (Exception e){
e.printStackTrace();
}
return "";
}
Try with new SimpleDateFormat("EEE dd MMM yyyy", Locale.ENGLISH);
Sample Code:
DateFormat originalFormat = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
DateFormat targetFormat = new SimpleDateFormat("EEE dd MMM yyyy", Locale.ENGLISH);
Date date = originalFormat.parse("01/04/2018");
String formattedDate = targetFormat.format(date); // Sun 01 Apr 2018
tl;dr
LocalDate
.parse(
"01/04/2018" ,
DateTimeFormatter // Parses & generates text in various formats
.ofPattern( "dd/MM/uuuu" ) // Define a formatting pattern to match your input.
) // Returns a `LocalDate` object.
.toString() // Generates text in standard ISO 8601 format.
2018-04-01
Use data types appropriately
I have a String in a database (match.getDate) that has the following date format:
Do not store date-time values as text.
You should be storing date-time values in a database using date-time data types. In standard SQL, a date-only value without time-of-day and without time zone is stored in a column of type DATE.
Another problem is that you are trying to represent a date-only value in Java class that represents a moment, a date with time-of-day in context of time zone or offset-from-UTC. Square peg, round hole. Using a date-only data types makes your problems go away.
java.time
The other Answers used outmoded classes, years ago supplanted by the modern java.time classes built into Java 8 and later, and built into Android 26 and later. For earlier Java & Android, see links below.
In Java, a date-only value without time-of-day and without time zone is represented by the LocalDate class.
LocalDate ld = LocalDate.parse( "2020-01-23" ) ; // Parsing a string in standard ISO 8601 format.
For a custom formatting pattern, use DateTimeFormatter.
String input = "01/04/2018" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) ;
LocalDate ld = LocalDate.parse( input , f ) ;
Generate a string in standard ISO 8601 format.
String output = ld.toString() ;
Generate a string in your custom format.
String output = ld.format( f ) ;
Tip: Use DateTimeFormatter.ofLocalizedDate to automatically localize your output.
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.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
first of check your match.getDate() method which format given date if is given above define format date then used below code and show date in define above format ...
String date="09/03/2018";
SimpleDateFormat parseDateFormat = new SimpleDateFormat("dd/MM/yyyy"); // if your match.getDate() given this format date.and if is given different format that time define that format.
DateFormat formatdate = new SimpleDateFormat("EEE dd MMM yyyy");
try {
Date date1=parseDateFormat.parse(date);
Log.d("New Date",formatdate.format(date1));
} catch (ParseException e) {
e.printStackTrace();
}
output:: Fri 09 Mar 2018

Parsing from SimpleDateFormat to Date not working?

SimpleDateFormat df = new SimpleDateFormat();
Date lastLogin = null;
try {
String troubleChild = lineScanner.next();
lastLogin = df.parse(troubleChild);
} catch (ParseException e) {
System.out.println("ohnoes");
}
Hi I'm quite new to using the date functions and I've come up with a problem. I have a file that is being parsed into various variables and they all work except this one i can never get it so that it passes the try/catch clause i've looked up similar problems but none of them work on my code.(The date i am inputting is in the format: Mon, Oct 30 22:20:11 GMT 2017) please can I get some help and thanks for it!
Solution: java.time
Please don’t take the trouble with the long outmoded classes Date and SimpleDateFormat. Instead use java.time, the modern Java date and time API also known as JSR-310:
DateTimeFormatter dtf
= DateTimeFormatter.ofPattern("E, MMM d H:mm:ss z uuuu", Locale.UK);
String inputDate = "Mon, Oct 30 22:20:11 GMT 2017";
ZonedDateTime lastLogin = ZonedDateTime.parse(inputDate, dtf);
System.out.println(lastLogin);
This prints
2017-10-30T22:20:11Z[GMT]
Since dates and times may come in so many different textual formats, I am using a format pattern string to specify your particular format. For which letters you may use, and what difference it makes whether you use 1, 3 or 4 of the same letter, see the documentation. Beware that format pattern strings are case sensitive.
Problem: SimpleDateFormat
You used the no-arg SimpleDateFormat constructor. The way I read the documentation, this gives you the default date format for your locale. If your JVM is running UK locale, I believe the format goes like 28/11/17 10:57 — not much like the input format you were trying to parse. You can use System.out.println(df.format(new Date())); to find out. The usual SimpleDateFormat constructor to use would be SimpleDateFormat(String, Locale) so that you may again supply a format pattern string and a locale.

Java.util.Date: try to understand UTC and ET more

I live in North Carolina, btw, which is on the East Side. So I compile and run this code and it print out the same thing. The documentation say that java.util.date try to reflect UTC time.
Date utcTime = new Date();
Date estTime = new Date(utcTime.getTime() + TimeZone.getTimeZone("ET").getRawOffset());
DateFormat format = new SimpleDateFormat("dd/MM/yy h:mm a");
System.out.println("UTC: " + format.format(utcTime));
System.out.println("ET: " + format.format(estTime));
And this is what I get
UTC: 11/05/11 11:14 AM
ET: 11/05/11 11:14 AM
But if I go to this website which try to reflect all different time, UTC and ET are different. What did I do wrong here
That's because getRawOffset() is returning 0 - it does that for me for "ET" as well, and in fact TimeZone.getTimeZone("ET") basically returns GMT. I suspect that's not what you meant.
The best Olson time zone name for North Carolina is "America/New_York", I believe.
Note that you shouldn't just add the raw offset of a time zone to a UTC time - you should set the time zone of the formatter instead. A Date value doesn't really know about a time zone... it's always just milliseconds since January 1st 1970 UTC.
So you can use:
import java.text.;
import java.util.;
Date date = new Date();
DateFormat format = new SimpleDateFormat("dd/MM/yy h:mm a zzz");
format.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println("Eastern: " + format.format(date));
format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
System.out.println("UTC: " + format.format(date));
Output:
Eastern: 11/05/11 11:30 AM EDT
UTC: 11/05/11 3:30 PM UTC
I'd also recommend that you look into using java.time now - which is much, mnuch better than the java.util classes.
according this post you habe to write TimeZone.getTimeZone("ETS") instead of TimeZone.getTimeZone("ET")
TimeZone.getTimeZone("ET").getRawOffset() is returning 0 this is why
The time zone you're looking for is "EST" or "EDT" (for Daylight time), not "ET". See http://mindprod.com/jgloss/timezone.html.
The proper abbreviation for Eastern Standard Time is "EST", not "ET". It looks like the getRawOffset() method returns 0 if it is passed an unknown time zone.
TimeZone.getTimeZone("EST").getRawOffset()
Also, when you output the utcTime variable, you are not outputting the UTC time. You are outputting EST time because you live in that timezone. From what I understand, the Date class internally stores the time in UTC...but when you format it in order to output it as a human-readable string, it takes the current locale/timezone into account.
Unknowingly, you have introduced two major problems in your code:
Not using the proper timezone name: The two/three/four letter timezone names (e.g. ET, EST, CEST etc.) are error-prone. The proper way of naming a timezone is Region/City e.g. Europe/London. In most cases, the Region is the name of the continent to which the City belongs.
Not using Locale with SimpleDateFormat: A parsing/formatting type e.g. the legacy, SimpleDateFormat or the modern, DateTimeFormatter are Locale-sensitive and therefore you should always use a Locale to avoid surprises. You can check this answer to learn more about it.
Also, note that a java.util.Date object is not a real Date-Time object like the modern Date-Time types; rather, it represents the number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT (or UTC). Since it does not hold any format and timezone information, it applies the format, EEE MMM dd HH:mm:ss z yyyy and the JVM's timezone to return the value of Date#toString derived from this milliseconds value. If you need to print the Date-Time in a different format and timezone, you will need to use a SimpleDateFormat with the desired format and the applicable timezone e.g.
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy hh:mm a zzz", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println(sdf.format(date));
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
System.out.println(sdf.format(date));
}
}
A sample output:
05/06/21 08:29 AM EDT
05/06/21 12:29 PM UTC
ONLINE DEMO
java.time
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*.
A demo using java.time, the modern API:
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
Instant now = Instant.now();
System.out.println(now);
ZonedDateTime zdtUTC = now.atZone(ZoneId.of("Etc/UTC"));
System.out.println(zdtUTC);
ZonedDateTime zdtNewYork = now.atZone(ZoneId.of("America/New_York"));
System.out.println(zdtNewYork);
}
}
A sample output:
2021-06-05T12:19:58.092338Z
2021-06-05T12:19:58.092338Z[Etc/UTC]
2021-06-05T08:19:58.092338-04:00[America/New_York]
ONLINE DEMO
Need output string in a different format?
You can use DateTimeFormatter for the output string in a different format e.g.
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
Instant now = Instant.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/uu hh:mm a zzz", Locale.ENGLISH);
ZonedDateTime zdtUTC = now.atZone(ZoneId.of("Etc/UTC"));
System.out.println(dtf.format(zdtUTC));
ZonedDateTime zdtNewYork = now.atZone(ZoneId.of("America/New_York"));
System.out.println(dtf.format(zdtNewYork));
}
}
A sample output:
05/06/21 12:34 PM UTC
05/06/21 08:34 AM EDT
ONLINE DEMO
Here, you can use yy instead of uu but I prefer u to y.
Learn more about java.time, the modern Date-Time API* from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

How to parse month full form string using DateFormat in Java?

I tried this:
DateFormat fmt = new SimpleDateFormat("MMMM dd, yyyy");
Date d = fmt.parse("June 27, 2007");
error:
Exception in thread "main" java.text.ParseException: Unparseable date: "June 27, 2007"
The java docs say I should use four characters to match the full form.
I'm only able to use MMM successfully with abbreviated months like "Jun" but i need to match full form.
Text: For formatting, if the number
of pattern letters is 4 or more, the
full form is used; otherwise a short
or abbreviated form is used if
available. For parsing, both forms are
accepted, independent of the number of
pattern letters.
https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html
You are probably using a locale where the month names are not "January", "February", etc. but some other words in your local language.
Try specifying the locale you wish to use, for example Locale.US:
DateFormat fmt = new SimpleDateFormat("MMMM dd, yyyy", Locale.US);
Date d = fmt.parse("June 27, 2007");
Also, you have an extra space in the date string, but actually this has no effect on the result. It works either way.
LocalDate from java.time
Use LocalDate from java.time, the modern Java date and time API, for a date
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("MMMM d, u", Locale.ENGLISH);
LocalDate date = LocalDate.parse("June 27, 2007", dateFormatter);
System.out.println(date);
Output:
2007-06-27
As others have said already, remember to specify an English-speaking locale when your string is in English. A LocalDate is a date without time of day, so a lot better suitable for the date from your string than the old Date class. Despite its name a Date does not represent a date but a point in time that falls on at least two different dates in different time zones of the world.
Only if you need an old-fashioned Date for an API that you cannot afford to upgrade to java.time just now, convert like this:
Instant startOfDay = date.atStartOfDay(ZoneId.systemDefault()).toInstant();
Date oldfashionedDate = Date.from(startOfDay);
System.out.println(oldfashionedDate);
Output in my time zone:
Wed Jun 27 00:00:00 CEST 2007
Link
Oracle tutorial: Date Time explaining how to use java.time.
Just to top this up to the new Java 8 API:
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("MMMM dd, yyyy").toFormatter();
TemporalAccessor ta = formatter.parse("June 27, 2007");
Instant instant = LocalDate.from(ta).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
Date d = Date.from(instant);
assertThat(d.getYear(), is(107));
assertThat(d.getMonth(), is(5));
A bit more verbose but you also see that the methods of Date used are deprecated ;-) Time to move on.
val currentTime = Calendar.getInstance().time
SimpleDateFormat("MMMM", Locale.getDefault()).format(date.time)

Categories