I'm a beginner in java programmeing.
I want to parse a complex date format : YYYY-MM-DDthh:mm:ssTZD, for example 2014-09-24T21:32:39-04:00
I tried this :
String str_date="2014-09-24T21:32:39-04:00";
DateFormat formatter = new SimpleDateFormat("YYYY-MM-DDthh:mm:ss");
Date date = (Date)formatter.parse(str_date);
But for the timezone part (-04:00), i have no idea what to put (after the :ss)
Any help ?
If you are using Java < 7 then you'd need to remove ':' from your input and parse it:
Here is an example:
public static void main(String[] args) throws ParseException {
String str_date="2014-09-24T21:32:39-04:00";
str_date = str_date.replaceAll(":(\\d\\d)$", "$1");
System.out.println("Input modified according to Java 6: "+str_date);
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date date = (Date)formatter.parse(str_date);
System.out.println(date);
}
prints:
Input modified according to Java 6: 2014-09-24T21:32:39-0400
Wed Sep 24 21:32:39 EDT 2014
Java7
SimpleDateFormat documentation lists the timezone as z, Z, and X and for you it looks like you want XXX.
Java6
Java7 added X specifier, but 6 still has the Z and z. However, you will have to modify the string first so that it either has no colon in the timezone or has GMT before the -:
String str_date="2014-09-24T21:32:39-04:00";
int index = str_date.lastIndexOf( '-' );
str_date = str_date.substring( 0, index ) + "GMT" + str_date.substring( index+1 );
Then you can use the format specifier z
ISO 8601
Your string complies with the ISO 8601 standard. That standard is used as the default in parsing and generating strings by two excellent date-time libraries:
Joda-Time
java.time package (bundled with Java 8, inspired by Joda-Time, defined by JSR 310)
Merely pass your string to the constructor or factory method. A built-in formatter is automatically used to parse your string.
Unlike java.util.Date, in these two libraries a date-time object knows its own assigned time zone. The offset from UTC specified at the end of your string is used to calculate a number of milliseconds (or nanoseconds in java.time) since the Unix epoch of the beginning of 1970 in UTC time zone. After that calculation, the resulting date-time is assigned a time zone of your choice. In this example I arbitrarily assign a India time zone. For clarity this example creates a second date-time object in UTC.
Joda-Time
DateTimeZone timeZoneIndia = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeIndia = new DateTime( "2014-09-24T21:32:39-04:00" , timeZoneIndia );
DateTime dateTimeUtc = dateTimeIndia.withZone( DateTimeZone.UTC );
Related
I'm trying to generate a random date and time, and convert it to the "yyyy-MM-dd'T'HH:mm:ss'Z'" format.
Here is what I have tried:
public static String generateRandomDateAndTimeInString() {
LocalDate date = LocalDate.now().minus(Period.ofDays((new Random().nextInt(365 * 70))));
System.out.println("date and time :: " + date.toString());
return formatDate(date) ;
}
public static String formatDate(LocalDate date){
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
return dateFormat.format(date);
}
But in the line dateFormat.format(date), it complains with:
java.lang.IllegalArgumentException: Cannot format given Object as a Date
The second problem is that, the output of print does not contain the time:
date :: 1998-12-24
I don't know how to get it to work.
Never format the java.time types using SimpleDateFormat
Using the SimpleDateFormat, you are supposed to format only legacy date-time types e.g. java.util.Date. In order to format the java.time date-time types, you need to use DateTimeFormatter.
Never enclose Z within single quotes
It's a blunder to enclose Z within single quotes in a format. The symbol Z stands for zulu and specifies UTC+00:00. If you enclose it within single quotes, it will simply mean character literal, Z and won't function as UTC+00:00 on parsing.
You do not need to use a formatter explicitly
For this requirement, you do not need to use a formatter explicitly because the OffsetDateTime#toString already returns the string in the format that you need. However, if the number of seconds in an OffsetDateTime object is zero, the same and the subsequent smaller units are truncated by OffsetDateTime#toString. If you need the full format irrespective of the value of seconds, then, of course, you will have to use DateTimeFormatter.
import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Random;
public class Main {
public static void main(String[] args) {
System.out.println(generateRandomDateAndTimeInString());
}
public static String generateRandomDateAndTimeInString() {
LocalDate date = LocalDate.now().minus(Period.ofDays((new Random().nextInt(365 * 70))));
System.out.println("date and time :: " + date.toString());
return formatDate(date);
}
public static String formatDate(LocalDate date) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssX");
// return date.atStartOfDay().atOffset(ZoneOffset.UTC).toString();
return date.atStartOfDay().atOffset(ZoneOffset.UTC).format(dtf);
}
}
A sample run:
date and time :: 1996-09-05
1996-09-05T00:00:00Z
Note that the date-time API of java.util 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.
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.
Learn more about the modern date-time API from Trail: Date Time.
If you still need to use SimpleDateFormat for whatsoever reason:
Convert LocalDate to ZonedDateTime with ZoneOffset.UTC and at the start of the day ➡️ Convert ZonedDateTime to Instant ➡️ Obtain java.util.Date object from Instant.
public static String formatDate(LocalDate date) {
Date utilDate = Date.from(date.atStartOfDay(ZoneOffset.UTC).toInstant());
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
return dateFormat.format(utilDate);
}
If you want to ignore the time part then you can use ZonedDateTime like this:
DateTimeFormatter dateFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
return ZonedDateTime.of(
date,
LocalTime.MIN,
ZoneId.of("Europe/Paris")
).format(dateFormat);
Output example
2013-10-19T00:00:00+0200
Or much better, you can use just toString to get a formatted date as a String with the default format of ZonedDateTime:
return ZonedDateTime.of(
date,
LocalTime.MIN,
ZoneId.of("Europe/Paris")
).toString();
Output
2013-10-19T00:00+02:00[Europe/Paris]
Note
This date are always with 00:00:00 for time part, because we are using LocalTime.MIN
Also, you can change the ZoneId to the expected Zone, this was just an example.
Important
DateFormat and SimpleDateFormat are legacy library, so please don't mix them with the java.time library, in the top you are using LocalDate which mean you are using this java.time library so keep going with it in all your code.
ZoneOffset utc = ZoneOffset.UTC;
LocalDate today = LocalDate.now(utc);
LocalDate seventyYearsAgo = today.minusYears(70);
int totalDays = Math.toIntExact(ChronoUnit.DAYS.between(seventyYearsAgo, today));
LocalDate date = today.minusDays(new Random().nextInt(totalDays));
String dateString = date.atStartOfDay(utc).toString();
System.out.println("date and time :: " + dateString);
Example output:
date and time :: 1983-08-24T00:00Z
Points to note:
Let java.time convert from years to days. It gives more readable and more correct code (a year is not always 365 days).
To have time of day and UTC offset in the string, convert a ZonedDateTime or an OffsetDateTime since such objects hold time of day and offset. A LocalDate does not. It’s a date without time of day and without offset from UTC. The Z you asked for denotes an offset of 0 from UTC.
If you want hours, minutes and seconds in the output too, you can have that by counting seconds rather than days. In this case use OffsetDateTime for the entire operation (or ZonedDateTime if in a time zone different from UTC).
ZoneOffset utc = ZoneOffset.UTC;
OffsetDateTime today = OffsetDateTime.now(utc).truncatedTo(ChronoUnit.SECONDS);
OffsetDateTime seventyYearsAgo = today.minusYears(70);
long totalSeconds = ChronoUnit.SECONDS.between(seventyYearsAgo, today);
OffsetDateTime date = today.minusSeconds(ThreadLocalRandom.current().nextLong(0, totalSeconds));
String dateString = date.toString();
System.out.println("date and time :: " + dateString);
date and time :: 1996-09-21T06:49:56Z
I am using ThreadLocalRandom because it can generate a random long value in a specified interval. Funnily ThreadLocalRandom has a lot of convenient methods that Random hasn’t got.
I have the following string "2015-04-02 11:52:00+02" and I need to parse it in Java to a Timestamp.
I tried all sorts of formats including
SimpleDateFormat mdyFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss+Z");
but nothing seems to work - I keep getting a ParseException
Can anyone help?
I need something like:
SimpleDateFormat mdyFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss+Z");
Timestamp t = new Timestamp(mdyFormat.parse("2015-04-02 11:52:00+02").getTime());
Try This
String str="2009-12-31 23:59:59 +0100";
/\
||
Provide Space while providing timeZone
SimpleDateFormat mdyFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
System.out.println(mdyFormat.parse(str));
Output
Fri Jan 01 04:29:59 IST 2010
java.sql.Timestamp objects don't have time zones - they are instants in time, like java.util.Date
So try this:
SimpleDateFormat mdyFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Timestamp t = new Timestamp(mdyFormat.parse("2015-04-02 11:52:00").getTime());
try "yyyy-MM-dd HH:mm:ssX"
Z stand for timezone in the following format: +0800
X stand for timezone in the following format: +08
Examples here
ISO 8601
Replace that SPACE in the middle with a T and you have a valid standard (ISO 8601) string format that can be parsed directly by either the Joda-Time library or the new java.time package built into Java 8 (inspired by Joda-Time). Search StackOverflow for hundreds of examples.
If using java.time, read my comment on Question about a bug when parsing hours-only offset value.
Example in Joda-Time 2.7.
String inputRaw = "2015-04-02 11:52:00+02";
String input = inputRaw.replace( " ", "T" );
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" ); // Specify desired time zone adjustment.
DateTime dateTime = new DateTime( input, zone );
I'm getting these times from Facebook events. E.g: start_time and it's a string like this:
2013-12-21T18:30:00+0100
Now I just want the time, like:
18.30
I tried to do it with this:
SimpleDateFormat formatter = new SimpleDateFormat(" EEEE, dd MMMM yyyy", java.util.Locale.getDefault());
Date formatted = null;
try {
formatted = formatter.parse(p.getStart_time());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String formattedString = formatted.toString();
txtStart_time.setText(""+formattedString);
p.getStart_time() is a String that gives me the date like I said before.
If I do this method, I get an error:
Unparseable date.
Does anybody know a work around?
You need two formats: one to parse the date and one to format it
String startTime = "2013-12-21T18:30:00+0100";
SimpleDateFormat incomingFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
Date date = incomingFormat.parse(startTime);
SimpleDateFormat outgoingFormat = new SimpleDateFormat(" EEEE, dd MMMM yyyy", java.util.Locale.getDefault());
System.out.println(outgoingFormat.format(date));
prints
Saturday, 21 December 2013
I'm getting these times from Facebook events. E.g: start_time and it's
a string like this:
2013-12-21T18:30:00+0100
Now I just want the time, like:
18.30
Solution using java.time, the modern date-time API:
OffsetDateTime.parse(
"2013-12-21T18:30:00+0100",
DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ")
).toLocalTime()
Description: Your date-time string has a timezone offset of +01:00 hours. java.time API provides you with OffsetDateTime to contain the information of date-time units along with the timezone offset. Using the applicable DateTimeFormatter, parse the string into an OffsetDateTime and then get the LocalTime part of this date-time using OffsetDateTime#toLocalTime.
Demo using java.time API:
import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
class Main {
public static void main(String[] args) {
System.out.println(OffsetDateTime.parse(
"2013-12-21T18:30:00+0100",
DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ssZ")
).toLocalTime());
}
}
Output:
18:30
ONLINE DEMO
Note: You can use y instead of u here but I prefer u to y.
Learn more about the modern Date-Time API from Trail: Date Time.
A note about the legacy API:
The question and the accepted answer use java.util.Date and SimpleDateFormat which was the correct thing to do in 2013. In Mar 2014, the java.util date-time API and their formatting API, SimpleDateFormat were supplanted by the modern date-time API. Since then, it is highly recommended to stop using the legacy date-time API.
Use something like yyyy-MM-dd'T'HH:mm:ssZ as parsing format instead of EEEE, dd MMMM yyyy.
Substring
If all you want is literally the time component lifted from that string, call the substring method on the String class…
// © 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 dateTimeStringFromFacebook = "2013-12-21T18:30:00+0100";
// Extract a substring.
String timeSubstring = dateTimeStringFromFacebook.substring( 11, 19 );
DateTime Object
If you want the time converted to a particular time zone, convert the string to a date-time object. Use a formatter to express just the time component.
Here is some example code using the Joda-Time 2.3 library. Avoid the notoriously bad java.util.Date/Calendar classes. Use either Joda-Time or the new java.time.* JSR 310 classes bundled with Java 8.
// From String to DateTime object.
DateTime dateTime = new DateTime( dateTimeStringFromFacebook, DateTimeZone.UTC );
// From DateTime object to String
// Extract just the hours, minutes, seconds.
DateTimeFormatter formatter = DateTimeFormat.forPattern("HH:mm:ss");
String timeFragment_Paris = formatter.withZone( DateTimeZone.forID( "Europe/Paris" ) ).print( dateTime );
String timeFragment_Kolkata = formatter.withZone( DateTimeZone.forID( "Asia/Kolkata" ) ).print( dateTime ); // Formerly known as Calcutta, India.
Dump to console…
System.out.println( "dateTimeStringFromFacebook: " + dateTimeStringFromFacebook );
System.out.println( "timeSubstring: " + timeSubstring );
System.out.println( "dateTime: " + dateTime );
System.out.println( "timeFragment_Paris: " + timeFragment_Paris );
System.out.println( "timeFragment_Kolkata: " + timeFragment_Kolkata + " (Note the 00:30 difference due to +05:30 offset)");
When run…
dateTimeStringFromFacebook: 2013-12-21T18:30:00+0100
timeSubstring: 18:30:00
dateTime: 2013-12-21T17:30:00.000Z
timeFragment_Paris: 18:30:00
timeFragment_Kolkata: 23:00:00 (Note the 00:30 difference due to +05:30 offset)
Think Time Zone
Your question fails to address the question of time zone. Make a habit of always thinking about time zone whenever working with date-time values. If you mean the same time zone, say so explicitly. If you mean the default time zone of the Java environment, say so. If you mean UTC… well, you get the idea.
// Im new to java programming
I have a String object that represents a date/time in this format : "2013-06-09 14:20:00" (yyyy-MM-dd HH:mm:ss)
I want to convert it to a Date object so i can perform calculations on it but im confused on how to do this.
I tried :
String string = "2013-06-09 14:20:00";
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(string);
System.out.println(date);
//Prints Mon Dec 31 00:00:00 GMT 2012
Any help appreciated
Ok so I have now updated my code to as follows i'm getting the correct date/time now when I print the date but is this the correct implementation :
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String string = "2013-06-09 14:20:00";
Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(string);
System.out.println(dateFormat.format(date));
//prints 2013-06-09 14:20:00
Thx to everyone that's answered/commented thus far
The format is wrong. Use this instead:
"yyyy-dd-MM HH:mm:ss"
Indeed your last program version is ok, except you don't need to declare the SimpleDateFormat twice. Simply:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String string = "2013-06-09 14:20:00";
Date date = dateFormat.parse(string);
System.out.println(dateFormat.format(date));
String string = "2013-06-09 14:20:00";
and the DATE object format is "yyyy-dd-MM HH:mm:ss"
You can get Date,Day,month and many more by using Date object which is present in
java.util.Date package , like as follows.
Date d = new Date(string);
This will call constructor of Date object for which you are passing 'string' variable which contains date.
d.getDay(); // retrieve day on that particular day
d.getDate(); // retrieve Date
and many more are avaiable like this.
Using java.util.Date
The answer by zzKozak is correct. Well, almost correct. The example code omits required exception handling. Like this…
java.text.DateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String string = "2013-06-09 14:20:00";
Date date = null;
try {
date = dateFormat.parse(string);
} catch ( ParseException e ) {
e.printStackTrace();
}
System.out.println("date: " + dateFormat.format(date));
Don't Use java.util.Date!
Avoid using java.util.Date & Calendar classes bundled with Java. They are notoriously bad in both design and implementation.
Instead use a competent date-time library. In Java that means either:
The third-party open-source Joda-Time
In the forthcoming Java 8, the new java.time.* classes defined by JSR 310 and inspired by Joda-Time.
Time Zone
Your question and code fail to address the issue of time zones. If you ignore time zones, you'll get defaults. That may cause unexpected behaviors when deployed in production. Better practice is to always specify a time zone.
Formatter
If you replace a space with a 'T' per the standard ISO 8601 format, then you can conveniently feed that string directly to a constructor of a Joda-Time DateTime instance.
If you must use that string as-is, then define a formatter to specify that format. You can find many examples of that here on StackOverflow.com.
Example Code
Here is some example code using Joda-Time 2.3, running in Java 7.
I arbitrarily chose a time zone of Montréal.
// © 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.*;
// Specify a time zone rather than rely on default.
// Necessary to handle Daylight Saving Time (DST) and other anomalies.
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTime = new DateTime( "2013-06-09T14:20:00", timeZone ); // Or pass DateTimeZone.UTC as time zone for UTC/GMT.
System.out.println( "dateTime: " + dateTime );
When run…
dateTime: 2013-06-09T14:20:00.000-04:00
I need to convert from one timezone to another timezone in my project.
I am able to convert from my current timezone to another but not from a different timezone to another.
For example I am in India, and I am able to convert from India to US using Date d=new Date(); and assigning it to a calendar object and setting the time zone.
However, I cannot do this from different timezone to another timezone. For example, I am in India, but I am having trouble converting timezones from the US to the UK.
tl;dr
ZonedDateTime.now( ZoneId.of( "Pacific/Auckland" )) // Current moment in a particular time zone.
.withZoneSameInstant( ZoneId.of( "Asia/Kolkata" )) // Same moment adjusted into another time zone.
Details
The java.util.Date class has no time zone assigned†, yet it's toString implementation confusingly applies the JVM's current default time zone.
Avoid java.util.Date & .Calendar
This is one of many reasons to avoid the notoriously troublesome java.util.Date, .Calendar, and SimpleDateFormat classes bundled with Java. Avoid them. Instead use either:
The java.time package built into Java 8 and inspired by Joda-Time.
Joda-Time
java.time
Java 8 and later has the java.time package built-in. This package was inspired by Joda-Time. While they share some similarities and class names, they are different; each has features the other lacks. One notable difference is that java.time avoids constructors, instead uses static instantiation methods. Both frameworks are led by the same man, Stephen Colbourne.
Much of the java.time functionality has been back-ported to Java 6 & 7 in the ThreeTen-Backport project. Further adapted to Android in the ThreeTenABP project.
In the case of this Question, they work in the same fashion. Specify a time zone, and call a now method to get current moment, then create a new instance based on the old immutable instance to adjust for time zone.
Note the two different time zone classes. One is a named time zone including all the rules for Daylight Saving Time and other such anomalies plus an offset from UTC while the other is only the offset.
ZoneId zoneMontréal = ZoneId.of("America/Montreal");
ZonedDateTime nowMontréal = ZonedDateTime.now ( zoneMontréal );
ZoneId zoneTokyo = ZoneId.of("Asia/Tokyo");
ZonedDateTime nowTokyo = nowMontréal.withZoneSameInstant( zoneTokyo );
ZonedDateTime nowUtc = nowMontréal.withZoneSameInstant( ZoneOffset.UTC );
Joda-Time
Some example code in Joda-Time 2.3 follows. Search StackOveflow for many more examples and much discussion.
DateTimeZone timeZoneLondon = DateTimeZone.forID( "Europe/London" );
DateTimeZone timeZoneKolkata = DateTimeZone.forID( "Asia/Kolkata" );
DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );
DateTime nowLondon = DateTime.now( timeZoneLondon ); // Assign a time zone rather than rely on implicit default time zone.
DateTime nowKolkata = nowLondon.withZone( timeZoneKolkata );
DateTime nowNewYork = nowLondon.withZone( timeZoneNewYork );
DateTime nowUtc = nowLondon.withZone( DateTimeZone.UTC ); // Built-in constant for UTC.
We have four representations of the same moment in the timeline of the Universe.
†Actually the java.util.Date class does have a time zone buried within its source code. But the class ignores that time zone for most practical purposes. So, as shorthand, it’s often said that j.u.Date has no time zone assigned. Confusing? Yes. Avoid the mess that is j.u.Date and go with Joda-Time and/or java.time.
Some examples
Convert time between timezone
Converting Times Between Time Zones
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.TimeZone;
public class TimeZoneExample {
public static void main(String[] args) {
// Create a calendar object and set it time based on the local
// time zone
Calendar localTime = Calendar.getInstance();
localTime.set(Calendar.HOUR, 17);
localTime.set(Calendar.MINUTE, 15);
localTime.set(Calendar.SECOND, 20);
int hour = localTime.get(Calendar.HOUR);
int minute = localTime.get(Calendar.MINUTE);
int second = localTime.get(Calendar.SECOND);
// Print the local time
System.out.printf("Local time : %02d:%02d:%02d\n", hour, minute, second);
// Create a calendar object for representing a Germany time zone. Then we
// wet the time of the calendar with the value of the local time
Calendar germanyTime = new GregorianCalendar(TimeZone.getTimeZone("Europe/Berlin"));
germanyTime.setTimeInMillis(localTime.getTimeInMillis());
hour = germanyTime.get(Calendar.HOUR);
minute = germanyTime.get(Calendar.MINUTE);
second = germanyTime.get(Calendar.SECOND);
// Print the local time in Germany time zone
System.out.printf("Germany time: %02d:%02d:%02d\n", hour, minute, second);
}
}
Date date = new Date();
String formatPattern = ....;
SimpleDateFormat sdf = new SimpleDateFormat(formatPattern);
TimeZone T1;
TimeZone T2;
// set the Calendar of sdf to timezone T1
sdf.setTimeZone(T1);
System.out.println(sdf.format(date));
// set the Calendar of sdf to timezone T2
sdf.setTimeZone(T2);
System.out.println(sdf.format(date));
// Use the 'calOfT2' instance-methods to get specific info
// about the time-of-day for date 'date' in timezone T2.
Calendar calOfT2 = sdf.getCalendar();
The "default" time zone can be avoided entirely by just setting the time zone appropriately for the Calendar object. However, I would personally suggest that you use Joda Time as a far superior API for date and time operations in Java. Amongst other things, time zone conversion is very simple in Joda.
It's not clear what your current code looks like and why you're only able to convert via the default time zone, but in Joda Time you'd just specify the time zone explicitly when creating (say) a DateTime object, and then use withZone(DateTimeZone zone).
If you could tell us more about how you're getting input data, we could give a fuller example.
You can use the following code snippet
String dateString = "14 Jul 2014 00:11:04 CEST";
date = formatter.parse(dateString);
System.out.println(formatter.format(date));
// Set the formatter to use a different timezone - Indochina Time
formatter.setTimeZone(TimeZone.getTimeZone("Asia/Bangkok"));
System.out.println("ICT time : "+formatter.format(date));
If you don't want to use Joda, here is a deterministic way using the built in libraries.
First off I recommend that you force your JVM to default to a timezone. This addresses the issues you might run into as you move your JVM from one machine to another that are set to different timezones but your source data is always a particular timezone. For example, lets say your data is always PDT/PST time zone, but you run on a box that is set to UTC timezone.
The following code snippet sets the default timezone in my JVM:
//You can either pass the JVM a parameter that
//enforces a TZ: java -Duser.timezone=UTC or you can do it
//programatically like this
TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");
TimeZone.setDefault(tz);
Now lets say your source date is coming in as PDT/PST but you need to convert it to UTC. These are the steps:
DateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC"));
String dateStrInPDT = "2016-05-19 10:00:00";
Date dateInPDT = dateFormat.parse(dateStrInPDT);
String dateInUtc = dateFormatUtc.format(dateInPDT);
System.out.println("Date In UTC is " + dateInUtc);
The output would be:
Date In UTC is 2016-05-19 17:00:00
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*.
Also, quoted below is a notice at the Home Page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
How to switch to the modern API?
Convert java.util.Date to Instant using Date#toInstant e.g.
Date date = new Date();
Instant instant = date.toInstant();
System.out.println(instant); // 2021-05-30T13:10:01.890Z
What's Instant got to do with my requirement?
An Instant represents an instantaneous point on the timeline in UTC. The Z in the sample output is the timezone designator for a zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours). Its zero-timezone offset makes it independent of timezones i.e. an instant is the same at every place in the world. It's analogous to water in the physical world.
You can mix a timezone (i.e. ZoneId) with an Instant by calling Instant.atZone to get the corresponding Date-Time in that timezone (i.e. ZonedDateTime).
Similarly, you can mix a timezone offset (i.e. ZoneOffset) with an Instant by calling Instant#atOffset to get the corresponding Date-Time with that timezone offset (i.e. OffsetDateTime).
In the reverse way, you can also get an Instant by calling toInstant on the ZonedDateTime or OffsetDateTime.
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Date;
public class Main {
public static void main(String[] args) {
Date date = new Date();
Instant instant = date.toInstant();
System.out.println(instant);
// The corresponding Date-Time in Chicago
ZonedDateTime zdtChicago = instant.atZone(ZoneId.of("America/Chicago"));
System.out.println(zdtChicago);
// The corresponding Date-Time in Kolkata
ZonedDateTime zdtKolkata = instant.atZone(ZoneId.of("Asia/Kolkata"));
System.out.println(zdtKolkata);
// The corresponding Date-Time at timezone offset of -05:00 hours
OffsetDateTime odtAtOffsetMinus0500 = instant.atOffset(ZoneOffset.of("-05:00"));
System.out.println(odtAtOffsetMinus0500);
// The corresponding Date-Time at timezone offset of +05:30 hours
OffsetDateTime odtAtOffset0530 = instant.atOffset(ZoneOffset.of("+05:30"));
System.out.println(odtAtOffset0530);
}
}
Output:
2021-05-30T13:44:26.599Z
2021-05-30T08:44:26.599-05:00[America/Chicago]
2021-05-30T19:14:26.599+05:30[Asia/Kolkata]
2021-05-30T08:44:26.599-05:00
2021-05-30T19:14:26.599+05:30
So far you have learnt a simple way to convert an Instant (which you have created directly or obtained from a java.util.Date or a ZonedDateTime or an OffsetDateTime) to a Date-Time in any timezone or at any timezone offset.
Alternatively
There is another way to convert a ZonedDateTime from one timezone to another. Again, there is a similar method to convert an OffsetDateTime from one timezone offset to another.
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
// Current Date-Time in Chicago
ZonedDateTime zdtChicago = ZonedDateTime.now(ZoneId.of("America/Chicago"));
System.out.println(zdtChicago);
// The corresponding Date-Time in Kolkata
ZonedDateTime zdtKolkata = zdtChicago.withZoneSameInstant(ZoneId.of("Asia/Kolkata"));
System.out.println(zdtKolkata);
// Current Date-Time at a timezone offset of -05:00 hours
OffsetDateTime odtAtOffsetMinus0500 = OffsetDateTime.now(ZoneOffset.of("-05:00"));
System.out.println(odtAtOffsetMinus0500);
// The corresponding Date-Time at timezone offset of +05:30 hours
OffsetDateTime odtAtOffset0530 = odtAtOffsetMinus0500.withOffsetSameInstant(ZoneOffset.of("+05:30"));
System.out.println(odtAtOffset0530);
}
}
Output:
2021-05-30T10:03:59.895923-05:00[America/Chicago]
2021-05-30T20:33:59.895923+05:30[Asia/Kolkata]
2021-05-30T10:03:59.897782-05:00
2021-05-30T20:33:59.897782+05:30
When to use ZonedDateTime and when to use OffsetDateTime?
If you are dealing with a fixed timezone offset value e.g. 02:00 hours, use OffsetDateTime. It is also supported by all JDBC drivers. Check this answer to learn more about it.
If you want the timezone offset to change automatically based on DST, use ZonedDateTime. Unfortunately, ZonedDateTime is not supported by JDBC.
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.
You could use the java.time.ZoneDateTime#ofInstant() method:
import java.time.*;
public class TimeZonesConversion {
static ZonedDateTime convert(ZonedDateTime time, ZoneId newTimeZone) {
return ZonedDateTime.ofInstant(
time.toInstant(),
newTimeZone);
};
public static void main(String... args) {
ZonedDateTime mstTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("-07"));
ZonedDateTime localTime = convert(mstTime, Clock.systemDefaultZone().getZone());
System.out.println("MST(" + mstTime + ") = " + localTime);
}
}
Depends on what you really mean by "converting".
It MAY be as simple as setting the time zone in the FORMATTER, and not mucking with Calendar at all.
Calendar cal = Calendar.getInstance();
TimeZone tzUTC = TimeZone.getTimeZone( "UTC" );
TimeZone tzPST = TimeZone.getTimeZone( "PST8PDT" );
DateFormat dtfmt = new SimpleDateFormat( "EEE, yyyy-MM-dd KK:mm a z" );
dtfmt.setTimeZone( tzUTC );
System.out.println( "UTC: " + dtfmt.format( cal.getTime() ));
dtfmt.setTimeZone( tzPST );
System.out.println( "PST: " + dtfmt.format( cal.getTime() ));
This is not the answer, but could help someone trying to generate dates with same timezone and apply another timezone's offset.
It is useful when your application server is running in one timezone and your database in another.
public static Date toGreekTimezone (Date date) {
ZoneId greek = ZoneId.of(EUROPE_ATHENS);
ZonedDateTime greekDate = ZonedDateTime.ofInstant(date.toInstant(), greek);
ZoneId def = ZoneId.systemDefault();
ZonedDateTime defDate = greekDate.withZoneSameLocal(def);
return Date.from(defDate.toInstant());
}
You can do something like this to get the current time in another time zone.
Calendar japanCal = new GregorianCalendar(TimeZone.getTimeZone("Japan"));
japanCal.setTimeInMillis(local.getTimeInMillis());
here a story:
my user in US enters a date in a web page. My server gets this as a java.util.Date object. Date objects have no notion of time zone.
so let's say user entered 11PM(== 4AM london time). For her this was 11PM US time.
Your server gets this and interprets this as 11PM of JVM's timezone.
but what you need is a Date object that represents 4AM.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String timeStringInUS = sdf.format("2020-05-04 23:00:00");
SimpleDateFormat dateFormatInUS = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat dateFormatInUK = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormatInUS.setTimeZone(TimeZone.getTimeZone("America/New_York"));
dateFormatInUK.setTimeZone(TimeZone.getTimeZone("Europe/London"));
Date dateInUS = dateFormatInUS.parse(timeStringInUS);
Date dateInUK = sdf.parse(dateFormatInUK.format(dateInUS));
public static String convertTimeBasedOnTimeZoneAndTimePattern(String dateTime,
String fromTimeZone, String toTimeZone, String originalTimePattern, String timePattern) {
DateTimeFormatter formatterNew = DateTimeFormatter.ofPattern(timePattern);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(originalTimePattern);
TemporalAccessor temporalAccessor = formatter.parse(dateTime);
ZoneId z = ZoneId.of(fromTimeZone);
LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, z);
Instant instant = Instant.from(zonedDateTime);
ZonedDateTime fromZonedDateTime = instant.atZone(ZoneId.of(toTimeZone));
String fromZoneDateTime = fromZonedDateTime.format(formatterNew);
return fromZoneDateTime;}
To convert any time to the specific timezone (for example: UTC -> local timezone and vise versa) with any time pattern you can use java.time library.
This method will take time patterns (original and required format) and timezone (original time zone and required timezone) will give String as output. you can convert String to date by using SimpleDateFormatter or also use parse method of the ZoneDateTime/Instant class.
To convert String to date:
public static final DATE_FORMAT="yyyy-MM-dd HH:mm:ss.SSSSS";
public static Date convertStringToDate(String date) {
SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
Date parsedDate = null;
try {
parsedDate = formatter.parse(date);
} catch (Exception e) {
throw new DateTimeParseException("Please provide date time in proper format", null, 0, null);
}
return parsedDate;
}
To convert date to String:
public String convertTextDateToDate(Date textDate) {
// SimpleDateFormat sdf = new SimpleDateFormat("EE MMM dd HH:mm:ss z yyyy", //Locale.ENGLISH);
SimpleDateFormat date = new SimpleDateFormat(DATE_FORMAT);
String dateFormatted = date.format(textDate);
return dateFormatted;
}