This question already has answers here:
Java: How do you convert a UTC timestamp to local time?
(3 answers)
Closed 8 years ago.
I have tried below code to convert the local date-time to a UTC date-time. But they are coming as same. I think I am missing something here. Can anyone please help me how can I get the UTC date time from local datetime 10/15/2013 09:00 AM GMT+05:30. This date time string I get from a outer system so if needed I can change the format.
SimpleDateFormat outputFormatInUTC = new SimpleDateFormat("MM/dd/yyyy hh:mm aaa z");
String startDateTime = "10/15/2013 09:00 AM GMT+05:30";
Date utcDate = outputFormatInUTC.parse(startDateTime);
ISO 8601 Format
Yes, if you can change the format of the string, you should. An international standard exists for this very purpose: ISO 8601. Like this 2013-12-26T21:19:39+00:00 or this 2013-12-26T21:19Z.
Joda-Time
Avoid using java.util.Date/Calendar classes. They are notoriously bad. Java 8 supplants them with new java.time.* JSR 310 classes. In the meantime, you can use the Joda-Time library which inspired JSR 310.
My example code below uses Joda-Time 2.3 running in Java 7 on a Mac.
Example Code
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
String string = "10/15/2013 09:00 AM GMT+05:30";
DateTimeFormatter formatter = DateTimeFormat.forPattern( "MM/dd/yyyy hh:mm aaa zZ" );
DateTime dateTime = formatter.parseDateTime( string );
System.out.println( "dateTime: " + dateTime );
When run…
dateTime: 2013-10-15T03:30:00.000Z
Just set TimeZone:
SimpleDateFormat outputFormatInUTC = new SimpleDateFormat("MM/dd/yyyy hh:mm aaa z");
String startDateTime = "10/15/2013 09:00 AM GMT+05:30";
outputFormatInUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
Date utcDate = outputFormatInUTC.parse(startDateTime);
String timeInUTC = outputFormatInUTC.format(utcDate);
System.out.println(timeInUTC);
Output:
10/15/2013 03:30 AM UTC
Try this:
SimpleDateFormat outputFormatInUTC = new SimpleDateFormat("MM/dd/yyyy hh:mm aaa z");
System.out.println(new Date()); //prints local date-time
outputFormatInUTC.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(outputFormatInUTC.format(new Date())); //prints UTC date-time
Related
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
This question already has answers here:
Android convert UTC Date to local timezone [duplicate]
(2 answers)
Closed 5 years ago.
I have a date String like 2017-09-16T05:06:18.157 and I want to convert it to local time (IST). In Indian Standard Time it will be around 2017-09-16 10:36:18.
With Joda-Time, I have tried to convert it to local but I was not able to do it.
Below is my code:
private String getConvertDate(String date_server) {
DateTimeFormatter inputFormatter = DateTimeFormat
.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
.withLocale(Locale.US);
DateTime parsed = inputFormatter.parseDateTime(date_server);
DateTimeFormatter outputFormatter = DateTimeFormat
.forPattern("yyyy-MM-dd HH:mm:ss")
.withLocale(Locale.US)
.withZone(DateTimeZone.getDefault());
return outputFormatter.print(parsed);
}
Good you found a solution with SimpleDateFormat. I'd just like to add more insights about it (basically because the old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs).
The input String (2017-09-16T05:06:18.157) contains only the date (year/month/day) and time (hour/minute/second/millisecond), but no timezone information. So, when calling parseDateTime, Joda-Time just assumes that it's in the JVM default timezone.
If you know that the input is in UTC, but the input itself has no information about it, you must tell it. One way is to set in the formatter:
// set the formatter to UTC
DateTimeFormatter inputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
.withZone(DateTimeZone.UTC);
// DateTime will be in UTC
DateTime parsed = inputFormatter.parseDateTime("2017-09-16T05:06:18.157");
Another alternative is to first parse the input to a org.joda.time.LocalDateTime (a class that represents a date and time without a timezone), and then convert it to a DateTime in UTC:
// parse to LocalDateTime
DateTime = parsed = LocalDateTime.parse("2017-09-16T05:06:18.157")
// convert to a DateTime in UTC
.toDateTime(DateTimeZone.UTC);
Both produces the same DateTime, corresponding to UTC 2017-09-16T05:06:18.157Z.
To format it to "IST timezone" (which is actually not a timezone - more on that below), you can also set the timezone in the formatter:
// convert to Asia/Kolkata
DateTimeFormatter outputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
.withZone(DateTimeZone.forID("Asia/Kolkata"));
System.out.println(outputFormatter.print(parsed));
Or you can convert the DateTime to another timezone, using the withZone() method:
DateTimeFormatter outputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
// convert to Asia/Kolkata
System.out.println(outputFormatter.print(parsed.withZone(DateTimeZone.forID("Asia/Kolkata"))));
Both will print:
2017-09-16 10:36:18
In your code you're using DateTimeZone.getDefault(), that gets the JVM default timezone (with some tricky details). But the default timezone can be changed without notice, even at runtime, so it's always better to specify which one you want to use.
Also, keep in mind that short names like IST are not real timezones. Always prefer to use IANA timezones names (always in the format Region/City, like Asia/Kolkata or Europe/Berlin).
Avoid using the 3-letter abbreviations (like IST or PST) because they are ambiguous and not standard. Just check in this list that IST can be "India Standard Time", "Israel Standard Time" and "Irish Standard Time".
You can get a list of available timezones (and choose the one that fits best your system) by calling DateTimeZone.getAvailableIDs().
Java new Date/Time API
Joda-Time is in maintainance mode and is being replaced by the new APIs, so I don't recommend start a new project with it. Even in joda's website it says: "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".
If you can't (or don't want to) migrate from Joda-Time to the new API, you can ignore this section.
In Android you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. To make it work, you'll also need the ThreeTenABP (more on how to use it here).
This new API has lots of different date/time types for each situation.
First, you can parse the input to a org.threeten.bp.LocalDateTime, then I use a org.threeten.bp.ZoneOffset to convert it to UTC, resulting in a org.threeten.bp.OffsetDateTime.
Then, I use a org.threeten.bp.ZoneId to convert this to another timezone, and use a org.threeten.bp.format.DateTimeFormatter to format it (this is basically what's suggested by #Ole V.V's comment - just to show how straightforward it is, as there aren't anything much different to do):
// parse to LocalDateTime
OffsetDateTime parsed = LocalDateTime.parse("2017-09-16T05:06:18.157")
// convert to UTC
.atOffset(ZoneOffset.UTC);
// convert to Asia/Kolkata
ZoneId zone = ZoneId.of("Asia/Kolkata");
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(outputFormatter.format(parsed.atZoneSameInstant(zone)));
The output is:
2017-09-16 10:36:18
try this code:
String serverdateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'";
public String convertServerDateToUserTimeZone(String serverDate) {
String ourdate;
try {
SimpleDateFormat formatter = new SimpleDateFormat(serverdateFormat, Locale.UK);
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Date value = formatter.parse(serverDate);
TimeZone timeZone = TimeZone.getTimeZone("Asia/Kolkata");
SimpleDateFormat dateFormatter = new SimpleDateFormat(serverdateFormat, Locale.UK); //this format changeable
dateFormatter.setTimeZone(timeZone);
ourdate = dateFormatter.format(value);
//Log.d("OurDate", OurDate);
} catch (Exception e) {
ourdate = "0000-00-00 00:00:00";
}
return ourdate;
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
TimeZone utcZone = TimeZone.getTimeZone("UTC");
simpleDateFormat.setTimeZone(utcZone);
Date myDate =simpleDateFormat.parse(rawQuestion.getString("Asia/Kolkata"));
simpleDateFormat.setTimeZone(TimeZone.getDefault());
String formattedDate = simpleDateFormat.format(myDate);
I am trying to Parse "8:30 AM" but I am getting Unparseable Date Exception.
From my UI side I am getting "8:30 AM" and "6:30 PM" kind of values but I have to convert that String into Date format and save that date in my database.
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test {
public static void main(String[] args) {
SimpleDateFormat timingFormat = new SimpleDateFormat("h a",
Locale.US);
String dateInString = "8:30 AM";
try {
// This line throws Unparseable exception
Date date = timingFormat.parse(dateInString);
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
From Documentation
the year value of the parsed Date is 1970 with GregorianCalendar if no
year value is given from the parsing operation. The TimeZone value may
be overwritten, depending on the given pattern and the time zone value
in text.
try this
SimpleDateFormat timingFormat = new SimpleDateFormat("h a", Locale.US);
Date date = timingFormat.parse("8 AM");
System.out.println(date.toString());
Output
Thu Jan 01 08:00:00 IST 1970
UPDATE
To get today date,you can try something like this after parsing
int hours = date.getHours();
Date today = new Date();
today.setHours(hours);
System.out.println(today);
Note getHours() and setHours are deprecated methods.Its recommended to go for Calendar.You will have to set hours, minutes explicitly.
UPDATE
if input is 8:30 or so,then you will have to parse it like this
SimpleDateFormat timingFormat = new SimpleDateFormat("h:mm a", Locale.US);
Date date = timingFormat.parse("8:30 AM");
System.out.println(date.toString());
Output
Thu Jan 01 08:30:00 IST 1970
Depending on the input,you need to select which kind of format you are insterested.You can check that whether string contains : or not,based on that you can use SimpleDateFormat.
Just to Parse 8:30 AM just change the formatter above with
SimpleDateFormat timingFormat = new SimpleDateFormat("h:mm a");
Regards
The accepted answer is correct but outdated.
As mentioned, the Question has an input string which means only a time-of-day while the java.util.Date class represents both a date plus a time-of-day.
What you need is a class that represents only a time-of-day. No such class in the older versions of Java before Java 8.
java.time
The java.time framework built into Java 8 and later supplants the troublesome old java.util.Date/.Calendar classes. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
LocalTime
The java.time classes include the LocalTime class. This class represents a time-of-day without any date nor time zone.
Note that for the formatter we specified a Locale using the English language to correctly identify the strings AM and PM which could vary by human language.
String input = "8:30 AM";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "h:m a" , Locale.ENGLISH );
LocalTime localTime = LocalTime.parse ( input , formatter );
Dump to console.
System.out.println ( "localTime: " + localTime );
localTime: 08:30
Database
Next, the database. Eventually we should see JDBC drivers updated to directly handle the java.time types. Until then, we must convert from java.time types to the old java.sql types.
Convert From java.time to java.sql
For this Question, that means the java.sql.Time class. That old java.sql.Time class has a new method for convenient conversions, valueOf.
java.sql.Time sqlTime = java.sql.Time.valueOf ( localTime );
From there, the JDBC driver converts from the java.sql time to the database type. For this Question, that probably means the standard TIME SQL type.
Pass java.sql.* Object To Database Via JDBC Driver
Use a PreparedStatement to insert or update your data by passing that sqlTime variable seen above. Search StackOverflow.com for countless examples of such insert/update work in SQL.
This question already has answers here:
SimpleDateFormat returns wrong time zone during parse
(2 answers)
Closed 1 year ago.
Code:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(new Date());
try {
String d = sdf.format(new Date());
System.out.println(d);
System.out.println(sdf.parse(d));
} catch (Exception e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
Output:
Thu Aug 08 17:26:32 GMT+08:00 2013
2013.08.08 09:26:32 GMT
Thu Aug 08 17:26:32 GMT+08:00 2013
Note that format() formats the Date correctly to GMT, but parse() lost the GMT details. I know I can use substring() and work around this, but what is the reason underlying this phenomenon?
Here is a duplicate question which doesn't have any answers.
Edit: Let me put the question in another way, what is the way to retrieve a Date object so that its always in GMT?
All I needed was this :
SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat sdfLocal = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
try {
String d = sdf.format(new Date());
System.out.println(d);
System.out.println(sdfLocal.parse(d));
} catch (Exception e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
}
Output : slightly dubious, but I want only the date to be consistent
2013.08.08 11:01:08
Thu Aug 08 11:01:08 GMT+08:00 2013
tl;dr
what is the way to retrieve a Date object so that its always in GMT?
Instant.now()
Details
You are using troublesome confusing old date-time classes that are now supplanted by the java.time classes.
Instant = 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() ; // Current moment in UTC.
ISO 8601
To exchange this data as text, use the standard ISO 8601 formats exclusively. These formats are sensibly designed to be unambiguous, easy to process by machine, and easy to read across many cultures by people.
The java.time classes use the standard formats by default when parsing and generating strings.
String output = instant.toString() ;
2017-01-23T12:34:56.123456789Z
Time zone
If you want to see that same moment as presented in the wall-clock time of a particular region, 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( "Asia/Singapore" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Same simultaneous moment, same point on the timeline.
See this code live at IdeOne.com.
Notice the eight hour difference, as the time zone of Asia/Singapore currently has an offset-from-UTC of +08:00. Same moment, different wall-clock time.
instant.toString(): 2017-01-23T12:34:56.123456789Z
zdt.toString(): 2017-01-23T20:34:56.123456789+08:00[Asia/Singapore]
Convert
Avoid the legacy java.util.Date class. But if you must, you can convert. Look to new methods added to the old classes.
java.util.Date date = Date.from( instant ) ;
…going the other way…
Instant instant = myJavaUtilDate.toInstant() ;
Date-only
For date-only, use LocalDate.
LocalDate ld = zdt.toLocalDate() ;
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?
Java SE 8, Java SE 9, and later
Built-in.
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
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
See How to use ThreeTenABP….
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.
OP's solution to his problem, as he says, has dubious output. That code still shows confusion about representations of time. To clear up this confusion, and make code that won't lead to wrong times, consider this extension of what he did:
public static void _testDateFormatting() {
SimpleDateFormat sdfGMT1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdfGMT1.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat sdfGMT2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
sdfGMT2.setTimeZone(TimeZone.getTimeZone("GMT"));
SimpleDateFormat sdfLocal1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
SimpleDateFormat sdfLocal2 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z");
try {
Date d = new Date();
String s1 = d.toString();
String s2 = sdfLocal1.format(d);
// Store s3 or s4 in database.
String s3 = sdfGMT1.format(d);
String s4 = sdfGMT2.format(d);
// Retrieve s3 or s4 from database, using LOCAL sdf.
String s5 = sdfLocal1.parse(s3).toString();
//EXCEPTION String s6 = sdfLocal2.parse(s3).toString();
String s7 = sdfLocal1.parse(s4).toString();
String s8 = sdfLocal2.parse(s4).toString();
// Retrieve s3 from database, using GMT sdf.
// Note that this is the SAME sdf that created s3.
Date d2 = sdfGMT1.parse(s3);
String s9 = d2.toString();
String s10 = sdfGMT1.format(d2);
String s11 = sdfLocal2.format(d2);
} catch (Exception e) {
e.printStackTrace();
}
}
examining values in a debugger:
s1 "Mon Sep 07 06:11:53 EDT 2015" (id=831698113128)
s2 "2015.09.07 06:11:53" (id=831698114048)
s3 "2015.09.07 10:11:53" (id=831698114968)
s4 "2015.09.07 10:11:53 GMT+00:00" (id=831698116112)
s5 "Mon Sep 07 10:11:53 EDT 2015" (id=831698116944)
s6 -- omitted, gave parse exception
s7 "Mon Sep 07 10:11:53 EDT 2015" (id=831698118680)
s8 "Mon Sep 07 06:11:53 EDT 2015" (id=831698119584)
s9 "Mon Sep 07 06:11:53 EDT 2015" (id=831698120392)
s10 "2015.09.07 10:11:53" (id=831698121312)
s11 "2015.09.07 06:11:53 EDT" (id=831698122256)
sdf2 and sdfLocal2 include time zone, so we can see what is really going on. s1 & s2 are at 06:11:53 in zone EDT. s3 & s4 are at 10:11:53 in zone GMT -- equivalent to the original EDT time. Imagine we save s3 or s4 in a data base, where we are using GMT for consistency, so we can have times from anywhere in the world, without storing different time zones.
s5 parses the GMT time, but treats it as a local time. So it says "10:11:53" -- the GMT time -- but thinks it is 10:11:53 in local time. Not good.
s7 parses the GMT time, but ignores the GMT in the string, so still treats it as a local time.
s8 works, because now we include GMT in the string, and the local zone parser uses it to convert from one time zone to another.
Now suppose you don't want to store the zone, you want to be able to parse s3, but display it as a local time. The answer is to parse using the same time zone it was stored in -- so use the same sdf as it was created in, sdfGMT1. s9, s10, & s11 are all representations of the original time. They are all "correct". That is, d2 == d1. Then it is only a question of how you want to DISPLAY it. If you want to display what is stored in DB -- GMT time -- then you need to format it using a GMT sdf. Ths is s10.
So here is the final solution, if you don't want to explicitly store with " GMT" in the string, and want to display in GMT format:
public static void _testDateFormatting() {
SimpleDateFormat sdfGMT1 = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
sdfGMT1.setTimeZone(TimeZone.getTimeZone("GMT"));
try {
Date d = new Date();
String s3 = sdfGMT1.format(d);
// Store s3 in DB.
// ...
// Retrieve s3 from database, using GMT sdf.
Date d2 = sdfGMT1.parse(s3);
String s10 = sdfGMT1.format(d2);
} catch (Exception e) {
e.printStackTrace();
}
}
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)