I have a datetime as 2011-01-11 01:51:10 and timezone as America/Los_Angeles
I want to get a localised date time for this value. This is what I do
val formatter1: DateTimeFormatter = DateTimeFormatter.ofPattern("y-M-d H:m:s");
val m1: LocalDateTime = LocalDateTime.parse("2011-01-11 01:51:10", formatter1);
println("DateTime: " + m1.atZone(ZoneId.of("America/Los_Angeles")))
The value that I get is
DateTime: 2011-01-11T01:51:10-08:00[America/Los_Angeles]
How do I convert it into localized datetime with -08:00 offset applied to it and no [America/Los_Angeles]?
You first have to specify which timezone that the time which you have parsed is in. Then specify an other one to convert into.
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("y-M-d H:m:s");
LocalDateTime m1 = LocalDateTime.parse("2011-01-11 01:51:10", formatter1);
ZonedDateTime z1 = m1.atZone(ZoneId.of("UTC"));
ZonedDateTime z2 = z1.withZoneSameInstant(ZoneId.of("America/Los_Angeles"));
System.out.println(z2.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
Looks like you are using java.time API which has a ZonedDateTime. You should probably use it instead of LocalDateTime, since that LocalDateTime does not have a time zone. From the docs:
A date without a time-zone in the ISO-8601 calendar system, such as 2007-12-03.
This class does not store or represent a time or time-zone. Instead, it is a description of the date, as used for birthdays. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.
And then, ZonedDateTime docs states that:
A date-time with a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30+01:00 Europe/Paris.
This class handles conversion from the local time-line of LocalDateTime to the instant time-line of Instant. The difference between the two time-lines is the offset from UTC/Greenwich, represented by a ZoneOffset.
Using a ZonedDateTime, your code would be like:
import java.time._
import java.time.format._
val zoneId = ZoneId.of("America/Los_Angeles")
val formatter = DateTimeFormatter.ofPattern("y-M-d H:m:s").withZone(zoneId)
val zdt = ZonedDateTime.parse("2011-01-11 01:51:10", formatter)
The result you will see at the console will be:
zdt: java.time.ZonedDateTime = 2011-01-11T01:51:10-08:00[America/Los_Angeles]
That happens because you are using the default toString method of ZonedDateTime and looks like the DateTimeFormatter.ISO_OFFSET_DATE_TIME is exactly what you want. So your code should be:
import java.time._
import java.time.format._
val zoneId = ZoneId.of("America/Los_Angeles")
val formatter = DateTimeFormatter.ofPattern("y-M-d H:m:s").withZone(zoneId)
val zdt = ZonedDateTime.parse("2011-01-11 01:51:10", formatter)
val formatted: String = zdt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
Please look into my complete answer for this. Answer
String dateTime = "MM/dd/yyyy HH:mm:ss";
String date = "09/17/2017 20:53:31";
Integer gmtPSTOffset = -8;
ZoneOffset offset = ZoneOffset.ofHours(gmtPSTOffset);
// String to LocalDateTime
LocalDateTime ldt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern(dateTime));
// Set the generated LocalDateTime's TimeZone. In this case I set it to UTC
ZonedDateTime ldtUTC = ldt.atZone(ZoneOffset.UTC);
System.out.println("UTC time with Timezone : "+ldtUTC);
// Convert above UTC to PST. You can pass ZoneOffset or ZoneId for 2nd parameter
LocalDateTime ldtPST = LocalDateTime.ofInstant(ldtUTC.toInstant(), offset);
System.out.println("PST time without offset : "+ldtPST);
// If you want UTC time with timezone
ZoneId zoneId = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdtPST = ldtUTC.toLocalDateTime().atZone(zoneId);
System.out.println("PST time with Offset and TimeZone : "+zdtPST);
probably what you want is to get UTC time and then apply timezone offset to it.
It's quite easy to do with Joda time. For example:
DateTime.now().minus(timezoneOffset)
where timezoneOffset is int that will represent time shift at your location. Correct me if I'm wrong.
Related
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.
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.
Java 8 has a completely new API for date and time. One of the most useful classes in this API is LocalDateTime, for holding a timezone-independent date-with-time value.
There are probably millions of lines of code using the legacy class java.util.Date for this purpose. As such, when interfacing old and new code there will be a need for converting between the two. As there seems to be no direct methods for accomplishing this, how can it be done?
Short answer:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());
Explanation:
(based on this question about LocalDate)
Despite its name, java.util.Date represents an instant on the time-line, not a "date". The actual data stored within the object is a long count of milliseconds since 1970-01-01T00:00Z (midnight at the start of 1970 GMT/UTC).
The equivalent class to java.util.Date in JSR-310 is Instant, thus there are convenient methods to provide the conversion to and fro:
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
A java.util.Date instance has no concept of time-zone. This might seem strange if you call toString() on a java.util.Date, because the toString is relative to a time-zone. However that method actually uses Java's default time-zone on the fly to provide the string. The time-zone is not part of the actual state of java.util.Date.
An Instant also does not contain any information about the time-zone. Thus, to convert from an Instant to a local date-time it is necessary to specify a time-zone. This might be the default zone - ZoneId.systemDefault() - or it might be a time-zone that your application controls, such as a time-zone from user preferences. LocalDateTime has a convenient factory method that takes both the instant and time-zone:
Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
In reverse, the LocalDateTime the time-zone is specified by calling the atZone(ZoneId) method. The ZonedDateTime can then be converted directly to an Instant:
LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());
Note that the conversion from LocalDateTime to ZonedDateTime has the potential to introduce unexpected behaviour. This is because not every local date-time exists due to Daylight Saving Time. In autumn/fall, there is an overlap in the local time-line where the same local date-time occurs twice. In spring, there is a gap, where an hour disappears. See the Javadoc of atZone(ZoneId) for more the definition of what the conversion will do.
Summary, if you round-trip a java.util.Date to a LocalDateTime and back to a java.util.Date you may end up with a different instant due to Daylight Saving Time.
Additional info: There is another difference that will affect very old dates. java.util.Date uses a calendar that changes at October 15, 1582, with dates before that using the Julian calendar instead of the Gregorian one. By contrast, java.time.* uses the ISO calendar system (equivalent to the Gregorian) for all time. In most use cases, the ISO calendar system is what you want, but you may see odd effects when comparing dates before year 1582.
Here is what I came up with ( and like all Date Time conundrums it is probably going to be disproved based on some weird timezone-leapyear-daylight adjustment :D )
Round-tripping: Date <<->> LocalDateTime
Given: Date date = [some date]
(1) LocalDateTime << Instant<< Date
Instant instant = Instant.ofEpochMilli(date.getTime());
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
(2) Date << Instant << LocalDateTime
Instant instant = ldt.toInstant(ZoneOffset.UTC);
Date date = Date.from(instant);
Example:
Given:
Date date = new Date();
System.out.println(date + " long: " + date.getTime());
(1) LocalDateTime << Instant<< Date:
Create Instant from Date:
Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);
Create Date from Instant (not necessary,but for illustration):
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
Create LocalDateTime from Instant
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);
(2) Date << Instant << LocalDateTime
Create Instant from LocalDateTime:
instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);
Create Date from Instant:
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
The output is:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
Instant from Date:
2013-11-01T14:13:04.574Z
Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
LocalDateTime from Instant:
2013-11-01T14:13:04.574
Instant from LocalDateTime:
2013-11-01T14:13:04.574Z
Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
Much more convenient way if you are sure you need a default timezone :
Date d = java.sql.Timestamp.valueOf( myLocalDateTime );
The fastest way for LocalDateTime -> Date is:
Date.from(ldt.toInstant(ZoneOffset.UTC))
Everything is here : http://blog.progs.be/542/date-to-java-time
The answer with "round-tripping" is not exact : when you do
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
if your system timezone is not UTC/GMT, you change the time !
the following seems to work when converting from new API LocalDateTime into java.util.date:
Date.from(ZonedDateTime.of({time as LocalDateTime}, ZoneId.systemDefault()).toInstant());
the reverse conversion can be (hopefully) achieved similar way...
hope it helps...
If you are on android and using threetenbp you can use DateTimeUtils instead.
ex:
Date date = DateTimeUtils.toDate(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
you can't use Date.from since it's only supported on api 26+
I'm not sure if this is the simplest or best way, or if there are any pitfalls, but it works:
static public LocalDateTime toLdt(Date date) {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);
ZonedDateTime zdt = cal.toZonedDateTime();
return zdt.toLocalDateTime();
}
static public Date fromLdt(LocalDateTime ldt) {
ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
GregorianCalendar cal = GregorianCalendar.from(zdt);
return cal.getTime();
}
I think below approach will solve the conversion without taking time-zone into consideration.
Please comment if it has any pitfalls.
LocalDateTime datetime //input
public static final DateTimeFormatter yyyyMMddHHmmss_DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatDateTime = datetime.format(yyyyMMddHHmmss_DATE_FORMAT);
Date outputDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(formatDateTime); //output
Can anybody tell me how to convert date to epoch in java.
e.g. 2011-05-01 13:12:20 IST or 2011-05-01 14:11:10 PST to epoch.
I am able to convert using 2011-05-01 13:12:20 format but when I use timezone alongwith it I am not getting correct result.
Construct a SimpleDateFormat with a string pattern that matches the date format you have. The "Date and Time" section and the "Examples" section should give you more than enough help on how to construct your date format string
Then simply do the following to get your date (with the appropriate date format string).
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date date = sdf.parse("15/01/2012");
java.time
Using the java.time classes.
String input = "2011-05-01 13:12:20".replace( " " , "T" );
LocalDateTime ldt = LocalDateTime.parse( input );
ZonedDateTime zdt = ldt.atZone( ZoneId.of( "Asia/Kolkata" ) );
If by “epoch”, you mean a count of whole seconds or milliseconds from the epoch reference date of first moment of 1970 in UTC (often referred to as Unix Time), then interrogate the ZonedDateTime object via an extracted Instant object.
long wholeSecondsSinceEpoch = zdt.toInstant().getEpochSecond();
long millisecondsSinceEpoch = zdt.toInstant().toEpochMilli();