I want to convert a timestamp (which is in GMT) to a local date and time.
This is what I have implemented so far, but it is giving me wrong month
Timestamp stp = new Timestamp(1640812878000L);
Calendar convertTimestamp = convertTimeStamp(stp,"America/Phoenix");
System.out.println(convertTimestamp.getTime());
public static Calendar convertTimeStamp( Timestamp p_gmtTime, String p_timeZone) throws Exception {
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy HH:MM:SS a", Locale.ENGLISH);
DateFormat formatter = DateFormat.getDateTimeInstance();
if (p_timeZone != null) {
formatter.setTimeZone(TimeZone.getTimeZone(p_timeZone));
} else {
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
}
String gmt_time = formatter.format(p_gmtTime);
Calendar cal = Calendar.getInstance();
cal.setTime(sdf.parse(gmt_time));
return cal;
}
Any help would be appreciated.
You cannot convert a timestamp to another timezone, cause timestamps are always GMT, they are a given moment in the line of time in the universe.
We humans are used to local time on our planet, so a timestamp can be formatted to be more human readable, and in that context it is converted to a local timezone.
Using legacy java.util.* packages, this is done as follows:
DateFormat tzFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
tzFormat.setTimeZone(TimeZone.getTimeZone("CET")); // Use whatever timezone
System.out.println(tzFormat.format(date));
If you need to make "math" over the timestamp on local timezone (like, tomorrow at 8:00 local timezone), then the situation is more complex.
To do this you can resort to a number of hacks (like parsing or modifying the string obtained with the method above), or use the new Java date & time classes that have a specific class to deal with date and time in local time zones:
Instant timestamp = Instant.ofEpochMilli(inputValue);
ZonedDateTime romeTime = timestamp.atZone(ZoneId.of("Europe/Rome"));
Note how this second example uses "Europe/Rome" and not generically "CET". This is very important if you're planning to deal with timezones where DST is used, cause the DST change day (or if they use DST or not) may change from country to country even if they are in the same timezone.
tl;dr
Instant
.ofEpochMilli( // Parse a count of milliseconds since 1970-01-01T00:00Z.
1_640_812_878_000L
) // Returns a `Instant` object.
.atZone( // Adjust from UTC to a time zone. Same moment, same point on the timeline, different wall-clock time.
ZoneId.of( "America/Phoenix" )
) // Returns a `ZonedDateTime` object.
.format( // Generat text representing the date-time value kept within that `ZonedDateTime` object.
DateTimeFormatter
.ofLocalizedDateTime( FormatStyle.MEDIUM )
.withLocale( Locale.US )
) // Returns a `String` object.
See this code run live at IdeOne.com.
Dec 29, 2021, 2:21:18 PM
Details
You are using terrible old date-time classes that were years ago supplanted by the modern java.time classes defined in JSR 310. Never use Timestamp, Calendar, Date, SimpleDateFormat, etc.
Use the Instant class to represent a moment as seen in UTC, with an offset of zero hours-minutes-seconds.
long millisecondsSinceBeginningOf1970InUtc = 1_640_812_878_000L ;
Instant instant = Instant.ofEpochMilli( millisecondsSinceBeginningOf1970InUtc ) ;
Specify the time zone in which you are interested.
ZoneID z = ZoneId.of( "Africa/Tunis" ) ;
Adjust from offset of zero to that time zone to produce a ZonedDateTime object.
ZonedDateTime zdt = instant.atZone( z ) ;
Generate text representing that moment by automatically localizing. Use a Locale to specify the human language to use in translation as well as a culture to use in deciding abbreviation, capitalization, order of elements, and so on.
Locale locale = Locale.JAPAN ; // Or Locale.US, Locale.ITALY, etc.
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.LONG ).withLocale( locale ) ;
String output = zdt.format( f ) ;
All of this has been addressed many times on Stack Overflow. Search to learn more.
Related
I want to convert string-presented date in custom format into ISO format.
The first step is pretty easy:
val parsed = DateTimeFormatter.ofPattern(pattern).parse(input)
Now I want to present this parsed value in ISO string, the problem is that input value can be
"13:35:23" with pattern "HH:mm:ss", and I want to be able to convert it to ISO as well, filling missed year/month/day etc with some default values, for example now(), so the resulting string will be for example 2020-07-09T13:35:23.000Z
Similar behaviour has toIsoString() method in JavaScript, if there are some ways to do that in Java?
P.S. Input can contain date/zone/ofset, so it is not only about parsing patterns like "HH:mm:ss"
tl;dr
Instead of thinking in terms of one elaborate formatting pattern for parsing, think in terms of combining parts.
Here we get the current moment as seen in UTC. Then we move to your desired time-of-day.
OffsetDateTime.now( ZoneOffset.UTC ).with( LocalTime.parse( "13:35:23" ) ).toInstant().toString()
Details
LocalTime
Parse your input appropriately.
LocalTime lt = LocalTime.parse( "13:35:23" ) ;
ZonedDateTime
Then combine with a date and time zone to determine a moment.
For any given moment, the date varies around the globe by time zone. So a time zone is crucial here.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate ld = LocalDate.now( z ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
Instant
Adjust to UTC, an offset of zero hours-minutes-seconds, by extracting a Instant.
Instant instant = zdt.toInstant() ;
Generate your string output, in standard ISO 8691 format.
String output = instant.toString() ;
OffsetDateTime
If you want the date and your time input to be seen as being for UTC eprather than some other time zone, use ZoneOffset.UTC constant. Use OffsetDateTime rather than ZonedDateTime. Use with to use al alternate part, such as here where we substitute the current time-of-day part with your input time-of-day.
OffsetDateTime // Represent a moment as date,time, and offset -from-UTC (a number of hours-minutes-seconds).
.now( ZoneOffset.UTC ) // Capture current moment as seen in UTC.
.with(
LocalTime.parse( "13:35:23" )
)
.toInstant() // Extract the more basic `Instant` object, always in UTC by definition.
.toString() // Generate text representing the value of this date-time object. Use standard ISO 8601 format.
If you used LocalTime.parse instead of DateTimeFormatter.parse directly, you would get a "local time" object, which you can then add to a "local date" giving you a date time:
LocalTime time = LocalTime.parse(input, DateTimeFormatter.ofPattern(pattern));
LocalDateTime dateTime = LocalDate.now().atTime(time)
You can then format dateTime in whatever format you want.
Use DateTimeFormatterBuilder to provide defaults.
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
class Main {
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter =
// builder for formatters
new DateTimeFormatterBuilder()
// append both patterns inclosed by []
.appendPattern("[yyyy-MM-dd HH:mm:ss][HH:mm:ss]")
// provide defaults for year, month and day
.parseDefaulting(ChronoField.YEAR_OF_ERA, now.getYear())
.parseDefaulting(ChronoField.MONTH_OF_YEAR, now.getMonthValue())
.parseDefaulting(ChronoField.DAY_OF_MONTH, now.getDayOfMonth())
// build the formatter
.toFormatter();
String a = "13:35:23";
String b = "1234-01-01 13:35:23";
System.out.println(LocalDateTime.parse(a, formatter));
System.out.println(LocalDateTime.parse(b, formatter));
System.out.println(formatter.parse(a));
System.out.println(formatter.parse(b));
}
}
how to add user timezone to utc
i am getting utc date like this
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-ddHH:mm:ss");
DateTime dateTime = formatter.withOffsetParsed().parseDateTime(getval[2]);
DateTime dateTimeUtc = dateTime.toDateTime(DateTimeZone.UTC);
Now i want to get user Timezone and add it to utc to convert that to localtime
UPDATE
i was able to get the user timezone but could add it to the utc
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-ddHH:mm:ss");
DateTime dateTime = formatter.withOffsetParsed().parseDateTime(getval[2]);
java.util.Calendar now = java.util.Calendar.getInstance();
java.util.TimeZone timeZone = now.getTimeZone();
DateTimeZone dtZone = DateTimeZone.forID(timeZone.getID());
DateTime dateTimeUtc = dateTime.toDateTime(DateTimeZone.UTC);
ofm.setDate(dateTimeUtc.toDateTime(dtZone).toDate());
This below code may help you to get the time zone of the user
//get Calendar instance
Calendar now = Calendar.getInstance();
//get current TimeZone using getTimeZone method of Calendar class
TimeZone timeZone = now.getTimeZone();
//display current TimeZone using getDisplayName() method of TimeZone class
System.out.println("Current TimeZone is : " + timeZone.getDisplayName());
also the below link helps you to convert user's timezone to UTC
link
java.time
The Joda-Time project was succeeded by the java.time framework defined in JSR 310. Here is the modern solution using those new classes found in Java 8 and later.
Your input format is nearly compliant with the ISO 8601 standard. The data is just missing the T between the date portion and the time-of-day portion, and is missing a Z on the end to indicate UTC. See if you can educate the publisher of your data about this important standard.
String input = "2019-01-23T01:23:45.123456789Z" ;
The java.time classes use the standard formats by default. So no need to specify a formatting pattern.
Instant instant = Instant.parse( input ) ;
instant.toString() = 2019-01-23T01:23:45.123456789Z
If you can get the input format changed, define a formatting pattern to match.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-ddHH:mm:ss" ) ;
Lacking any indicator of time zone or offset, we must parse as a LocalDateTime. Note that such an object does not represent a moment, is not a specific point on the timeline.
String input = "2019-01-2301:23:45" ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;
ldt.toString() = 2019-01-23T01:23:45
You claim to be sure this date and time were intended to represent a moment in UTC. So we can apply an offset using the constant ZoneOffset.UTC to produce a OffsetDateTime.
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;
odt.toString() = 2019-01-23T01:23:45Z
Then you said you want to adjust this into a specific time zone. Same moment, same point on the timeline, but different wall-clock time.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
zdt.toString() = 2019-01-23T02:23:45+01:00[Africa/Tunis]
As you can see, Tunisia on that date was running an hour ahead of UTC. So the time-of-day appears to be 2 AM rather than 1 AM.
Here's a small example that gets the difference from a list of time zones (in hours):
import java.util.Date;
import java.util.TimeZone;
public class StackOverflowTimeZone {
public static void main(String[] a) {
Date date = new Date();
for(int index = 0; index < TimeZone.getAvailableIDs().length; index++) {
System.out.println(TimeZone.getAvailableIDs()[index] + " offset from UTC: " + TimeZone.getTimeZone(TimeZone.getAvailableIDs()[index]).getOffset(date.getTime()) / (60 * 60 * 1000) + " hours.");
}
}
}
The abstract class TimeZone was designed to get the offset of a designated time zone from Coordinated Universal Time (UTC). There is a list of time zones that can be found by using the method TimeZone.getAvailableIDs(). After getting the offset, you will need to do a few small calculuations in order to find out whether the designated time zone is ahead or behind UTC. The sign (+/-) of your output should correlate to whether that designated time zone is ahead or behind UTC.
I must convert a linux timestamp to android date.
i get this number from server
1386889262
I have written a small code snippet.
Date d = new Date(jsonProductData.getLong(MTIME));
SimpleDateFormat f = new SimpleDateFormat("dd.MM.yyyy");
.setTimeZone(TimeZone.getTimeZone("GMT"));
formatTime = f.format(d);
but it doesen't convert right, this is my result
17.01.1970
EDIT:
Normally i must get this here
12.12.2013
Is there an another method to get the right date???
if your UNIX time stamp is of 10 digit then it does not include milliseconds so do this first 1386889262*1000
and if its 13 digit then it includes milliseconds also then you do not have to multiply unix timestamp with 1000.
In Kotlin we can use this function:
val unix=1386889262*1000 /*if time stamp is of 10 digit*/
val dateFormat = SimpleDateFormat("dd-MM-yy HH:mm:ss");
val dt = Date(unix);
textview.settext(dateFormat.format(dt))
UNIX timestamp should be in milliseconds so multiply the Long value by 1000. So your value 1386889262 would be 1386889262000:
tl;dr
Instant.ofEpochSecond( 1386889262L )
.atZone( ZoneId.of( "Pacific/Auckland" ) )
.toLocalDate()
.toString()
java.time
You appear to have a count of whole seconds from the epoch reference date of first moment of 1970 in UTC, 1970-01-01T00:00:00Z.
The modern approach uses the java.time classes that supplant the troublesome old date-time classes bundled with the earliest versions of Java. For older Android see the ThreeTen-Backport and ThreeTenABP projects.
An Instant represents a point on the timeline in UTC with a resolution of nanoseconds (up to nine digits of decimal fraction).
Instant instant = Instant.ofEpochSecond( 1386889262L ) ;
To generate a String representing this moment, call toString.
String output = instant.toString() ;
Determining a date requires a time zone. For any given moment, the date varies around the globe by zone. Assign a ZoneId to get a ZonedDateTime object.
ZoneId z = ZoneId.of( "Africa/Casablanca" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
Extract a date-only value for your purposes.
LocalDate ld = zdt.toLocalDate() ;
Generate a String.
String output = ld.toString() ;
For other formats in your String, search Stack Overflow for DateTimeFormatter.
Your timestamp or epoch time seems in sec "1386889262". You have to do something like this:
long date1 = 1386889262*1000;
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yy HH:mm");
Date dt = new Date(date1);
datedisplay.setText(dateFormat.format(dt));
You can also get timestamp in java via
new Date().getTime() ;
It returns a long value.
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("PST"));
cal.setTime(new Date());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a");
Date resultdate = new Date(cal.getTimeInMillis());
sdf.setTimeZone(TimeZone.getTimeZone("PST"));
System.out.println("String date:"+sdf.format(resultdate));
System.out.println("Date:"+sdf.parse(sdf.format(resultdate)));
output:
String date:2011-12-29 09:01:58 PM
Date:Fri Dec 30 10:31:58 IST 2011
Problem:
sdf.format(resultdate) returning correct date and time to as per timezone. But,
sdf.parse(sdf.format(resultdate)) not returning correct date and time to as per timezone, how to fix this problem?
The Date class is merely a thin wrapper around the number of milli-seconds past the 'epoch' (January 1, 1970, 00:00:00 GMT). It doesn't store any timezone information. In your last call you are adding a date instance to a String which implicitly calls the toString() method. The toString() method will use the default timezone to create a String representing the instance (as it doesn't store any timezone info). Try modifying the last line to avoid using the toString() method.
System.out.println("Date:" + sdf.format(sdf.parse(sdf.format(resultdate))));
Try using joda-Time api for your convenience. Example is here
Unfortunatley Java date returns time in GMT only. When ever you want display in front end or some where, you need to use the formated String generated in your step1.
try the below code will, it will work.
Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("PST"));
cal.setTime(new Date());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a");
Date resultdate = new Date(cal.getTimeInMillis());
sdf.setTimeZone(TimeZone.getTimeZone("PST"));
System.out.println("String date:"+sdf.format(resultdate));
System.out.println("Date:"+sdf2.parse(sdf.format(resultdate)));
Three-Letter Time Zone Codes
Avoid using the three-letter time zone codes. They are neither standardized nor unique. For example, IST means both India Standard Time and Irish Standard Time. Furthermore, the codes are meant to distinguish Daylight Saving Time (DST) but that only confuses matters.
Use proper descriptive time zone names to retrieve a time zone object that encompasses DST and other issues.
Joda-Time
The java.util.Date & Calendar classes bundled with Java are notoriously troublesome. Avoid them. Use Joda-Time or the new java.time.* package bundled with Java 8.
In JodaTime, a DateTime object truly knows its own time zone (unlike java.util.Date). Usually we use the immutable classes in Joda-Time. So instead of changing the time zone in a DateTime object, we create a fresh new DateTime object based on the old but with a specified difference. A different time zone might be that difference.
Here is some example code.
DateTimeZone timeZone_India = DateTimeZone.forID( "Asia/Kolkata" );
DateTimeZone timeZone_Ireland = DateTimeZone.forID( "Europe/Dublin" );
DateTimeZone timeZone_US_West_Coast = DateTimeZone.forID( "America/Los_Angeles" );
DateTime now = new DateTime( timeZone_India );
System.out.println( "now in India: " + now );
System.out.println( "now in Ireland: " + now.withZone( timeZone_Ireland ) );
System.out.println( "now in US West Coast: " + now.withZone( timeZone_US_West_Coast ) );
System.out.println( "now in UTC/GMT: " + now.withZone( DateTimeZone.UTC ) );
When run…
now in India: 2014-02-10T13:52:27.875+05:30
now in Ireland: 2014-02-10T08:22:27.875Z
now in US West Coast: 2014-02-10T00:22:27.875-08:00
now in UTC/GMT: 2014-02-10T08:22:27.875Z
java.time
Same idea using the java.time classes which supplant Joda-Time.
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();
Apply a time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );
The instant and the zdt represent the same moment, the same point on the timeline. Each is seen through the lens of a different region’s wall-clock time.
Generate a String by either specifying a formatting pattern or by letting java.time automatically localize.
To localize, specify:
FormatStyle to determine how long or abbreviated should the string be.
Locale to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, and such.
Example:
Locale l = Locale.CANADA_FRENCH ;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( l );
String output = zdt.format( f );
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;
}