Converting UTC timestamp to local date - java

So I tried now for about hours to convert a Timestamp to a local date (CEST).
Date date = new Date(stamp*1000);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("CEST"));
String myDate = simpleDateFormat.format(date);
It's not working whatever I tried and looked up in Internet I always get back the UTC time......
for better understanding: stamp is a variable timestamp with type long which I will receive from a service

tl;dr
String output = ZonedDateTime.ofInstant ( Instant.ofEpochSecond ( 1_468_015_200L ) , ZoneId.of ( "Europe/Paris" ) ).toString();
Details
A few issues:
You are not using proper time zone names.
Proper names are in continent/region format.
The 3-4 letter abbreviations so commonly seen in the media such as CEST are not true time zones. Avoid them. They are neither standardized nor unique(!).
You are using old outmoded date-time classes that are poorly designed and confusing. They have been supplanted by the java.time framework.
If by CEST you meant 2 hours ahead of UTC in the summer, then let's take Europe/Paris as an example time zone. Your Question lacks example data, so I'll make up this example.
Apparently your input is a count of whole seconds from the epoch of first moment of 1970 in UTC. That value can be used directly, no need to multiply.
The ZoneId class represents the time zone. An Instant is a point on the timeline in UTC with a resolution up to nanoseconds. A ZonedDateTime is the Instant adjusted into the ZoneId.
ZoneId zoneId = ZoneId.of ( "Europe/Paris" );
long input = 1_468_015_200L; // Whole seconds since start of 1970.
Instant instant = Instant.ofEpochSecond ( input );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
Dump to console.
System.out.println ( "input: " + input + " | instant: " + instant + " | zdt: " + zdt );
input: 1468015200 | instant: 2016-07-08T22:00:00Z | zdt: 2016-07-09T00:00+02:00[Europe/Paris]

Your TimeZone id is likely to be incorrect (well, not recognized by Java). It seems that instead of throwing an exception the TimeZone is evaluated to UTC in that case.
Try this instead:
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("ECT"));
Here is a page giving some information about Java's TimeZone and a list of timezone ids.

Related

java.text.ParseException: Unparseable date: "09:07:31 AM PDT"

I have a field in the response that is coming as time which I want to parse before adding some minutes into it. I have written the below code which results in error.
SimpleDateFormat df = new SimpleDateFormat("HH:MM:ss a SSS");
Date date = df.parse(currentTime);
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.add(Calendar.MINUTE, 10);
here, currentTime is coming in as "09:07:31 AM PDT"
tl;dr
LocalTime // Represent a time-of-day without a date and without a time zone or offset-from-UTC.
.parse(
"09:07:31 AM PDT".substring( 0 , 11 ) , // Remove the senseless `PDT` from the input.
DateTimeFormatter.ofPattern( "hh:mm:ss a" ) // Define a formatting pattern to match our modified input string.
) // Returns a `LocalTime` object.
.toString() // Generates text in standard ISO 8601 format to represent the value of our `LocalTime` object.
09:07:31
Avoid Date & Calendar
You are using terrible date-time classes that were bundled with the earliest versions of Java. These were supplanted years ago by the modern java.time classes defined in JSR 310.
Never use Date, Calendar, SimpleDateFormat, and such.
Date class does not fit
The java.util.Date class represents a moment, a date with time-of-day, as seen in UTC. Your input lacks a date. So your input cannot be represented by this class.
Time-of-day with zone makes no sense
Your input represents a time-of-day with what is a false time zone. The PDT likely stands for "Pacific Daylight Saving Time", to indicate whether Daylight Saving Time (DST) is in effect or not. This is not a true time zone name. Instead a time zone name such as America/Los_Angeles should be used.
At any rate, the combination of a time-of-day with a time zone makes no sense. Without the context of a date, the time zone carries no meaning.
LocalTime
I suggest you extract the time-of-day and ignore the PDT. Take the first 11 characters.
String input = "09:07:31 AM PDT";
String s = input.substring( 0 , 11 ); // Uses annoying zero-based index counting. So asking for first through the eleventh characters requires ( 0 , 11 ).
Define a formatting pattern to match our modified input string.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "hh:mm:ss a" );
Parse as a LocalTime, a time-of-day without a date and without a time zone or offset-from-UTC.
LocalTime lt = LocalTime.parse( s , f );
lt.toString(): 09:07:31
ZonedDateTime
For fun, let's apply a time zone to your time-of-day, and a date to get a ZonedDateTime.
LocalTime lt = LocalTime.parse( "01:59:00 AM PDT".substring( 0 , 11 ) , DateTimeFormatter.ofPattern( "hh:mm:ss a" ) );
LocalDate ld = LocalDate.of( 2020 , Month.MARCH , 7 );
ZoneId z = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );
ZonedDateTime zdtLater = zdt.plusMinutes( 5 );
System.out.println( "zdtLater = " + zdtLater );
We get 2:04 AM.
zdtLater = 2020-03-07T02:04-08:00[America/Los_Angeles]
Change that date to the 8th.
LocalTime lt = LocalTime.parse( "01:59:00 AM PDT".substring( 0 , 11 ) , DateTimeFormatter.ofPattern( "hh:mm:ss a" ) );
LocalDate ld = LocalDate.of( 2020 , Month.MARCH , 8 );
ZoneId z = ZoneId.of( "America/Los_Angeles" );
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z );
ZonedDateTime zdtLater = zdt.plusMinutes( 5 );
System.out.println( "zdtLater = " + zdtLater );
We get 3:04 AM, not 2:04 AM.
zdtLater = 2020-03-08T03:04-07:00[America/Los_Angeles]
The date is what gives meaning to that time-of-day in a time zone.
Offsets vary over time. That is the meaning of a time zone. A time zone such as America/Los_Angeles is a history of the past, present, and future changes to the offset used by the people in many regions on the west coast of North America. On March 7, 2020 the offset was eight hours behind UTC. On March 8, 2020, the offset was changed to seven hours behind UTC. At the first moment of 2 AM, the clock jumped an hour to 3 AM. The 2 AM hour never happened on the 8th as it did on the 7th.
OffsetTime
The java.time framework does offer the OffsetTime class. This represents a time-of-day with an offset-from-UTC.
This class makes no sense, for the same reasons discussed above. A time-of-day with an offset but no date serves no useful purpose. I presume this was added to java.time merely to match the SQL-standard type TIME WITH TIME ZONE, in parallel with LocalTime matching TIME WITHOUT TIME ZONE. But this TIME WITH TIME ZONE type makes no sense in SQL. This problem is noted by others, not merely my opinion. And this is not the only senseless thing in the SQL standard.
Furthermore, your input carries a time zone (or at least a time zone was intended by the mis-use of PDT), not an offset. An offset is a number of hour-minutes-seconds, nothing more. A time zone is a history of changes in offset, as discussed above.
You need to use the right combination of letters in format, here:
SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss aa zzz");
You might also want to look at API docs [1].
Note: Parsing would work if you use the above format, but you will need the date part as well for accurate calculations. Here is an example with the current date of the current timezone of your machine used as the date part.
String recievedTime = "09:07:31 AM PDT";
String currentDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss aa zzz");
Date date = df.parse(currentDate +" " + recievedTime);
[1] https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html

UTC time in java? [duplicate]

This question already has answers here:
How can I get the current date and time in UTC or GMT in Java?
(33 answers)
Closed 4 years ago.
How can I get UTC value in Java of any given time and date with the respective time-zone?
Say for example my current time zone is Asia/Kolkata, now how can I get UTC value of say 1.00 am on 21/07/2018?
For getting currect time in UTC.
Instant.now() // Current time in UTC.
For getting current time in any desired TimeZone.
ZonedDateTime.now( ZoneId.systemDefault() ) // Current time in your ZoneId.
Kolkata Example :
ZoneId zoneKolkata = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zoneDTKolkata = instant.atZone( zoneKolkata ) ;
To adjust back to UTC, extract an Instant from the ZonedDateTime.
Instant instant = zoneDTKolkata.toInstant() ;
You can adjust from UTC to a time zone.
ZonedDateTime zoneDTKolkata = instant.atZone( zoneKolkata ) ;
Use the Java 8 time API instead of the older API (ie Date & SimpleDateFormat solution proposed by rajadilipkolli)
// System time (ie, your operating system time zone)
LocalDateTime ldt = LocalDateTime.of(year, month, day, hour, minute, second);
// Time in Asia/Kolkata
ZonedDateTime kolkata = ldt.atZone(ZoneId.of("Asia/Kolkata"));
// Time in UTC
OffsetDateTime utc = ldt.atOffset(ZoneOffset.UTC);
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("h.mm a 'on' dd/MM/uuuu")
.toFormatter(Locale.ENGLISH);
ZoneId zone = ZoneId.of("Asia/Kolkata");
String localDateTimeString = "1.00 am on 21/07/2018";
Instant i = LocalDateTime.parse(localDateTimeString, formatter)
.atZone(zone)
.toInstant();
System.out.println("UTC value is: " + i);
This prints:
UTC value is: 2018-07-20T19:30:00Z
I wasn’t sure whether you needed to parse the exact string you gave, 1.00 am on 21/07/2018, into a date-time object, but in case I have shown how. The challenge is that am is in lowercase. In order to specify case insensitive parsing I needed to go through a DateTimeFormatterBuilder.
As you can see, the code converts to an Instant, which is the modern way to represent a point in time in Java. Instant.toString always prints the time in UTC. The Z at the end means UTC. If you want a date-time that is more explicitly in UTC you may use
OffsetDateTime odt = LocalDateTime.parse(localDateTimeString, formatter)
.atZone(zone)
.toInstant()
.atOffset(ZoneOffset.UTC);
System.out.println("UTC value is: " + odt);
The output is similar, only OffsetDateTime leaves out the seconds if they are 0 (zero):
UTC value is: 2018-07-20T19:30Z
Link: Oracle tutorial: Date Time explaining how to use java.time, the modern Java date and time API.

Java - Adding/appending time start time(00:00:00.000) & end time (23.59.59.999) to date

I'm getting start date as "2016-06-01" and end date as "2016-07-01" (in string format) for searching records in MongoDB. Need pointer/guidance to append start time (00:00:00.000) to start date and maximum time(23.59.59.999) to end date as below in Java using java.util.Date or any others which supported by MongoDB.
Example :
Start Date+with time : 2016-06-01T00:00:00.000
End Date+with time : 2016-07-01T23:59:59.999
You could use the DateTimeFormatter.ISO_LOCAL_DATE_TIME for this. Here is an example that might shed some light on what you are trying to do:
DateTimeFormatter dtf = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
String startTime = "T00:00:00.000";
String endTime = "T23:59:59.999";
//here I used the LocalDateTime parser to parse the data+startTime/endTime
LocalDateTime startLocalDateTime = LocalDateTime.parse("2016-07-01"+startTime);
LocalDateTime endLocalDateTime = LocalDateTime.parse("2016-07-01"+endTime );
//with the LocalDateTime, you can then to whatever you want
//as an example, I am parsing it using ISO_LOCAL_DATE_TIME :
String strinStartTime= dtf.format(LocalDateTime.parse("2016-07-22"+startTime));
I hope this helps;
tl;dr
ZoneId zoneId = ZoneId.of( "Europe/Paris" ) ;
LocalDate startDate = LocalDate.of( "2016-06-01" ) ;
ZonedDateTime zdt start = startDate.atStartOfDay( zoneId ) ;
ZonedDateTime zdt stop = startDate.plusMonths(1).atStartOfDay( zoneId ) ;
// Perform database search where ( ( x >= start ) AND ( x < stop ) ) . Notice '>=' versus '<' with no 'equals' on the latter.
If you need strings…
String outputStart = start.toInstant().toString() ; // 2016-05-31T22:00:00Z Paris in the summer is two hours ahead of UTC.
String outputStop = stop.toInstant().toString() ; // 2016-06-30T22:00:00Z
Details
The Answer by ishmaelMakitla is good in that it points to using the java.time classes built into Java 8 and later. But it focuses on strings rather than objects. Also it does not discuss the crucial issue of time zone.
The java.time classes include:
LocalDate for a date-only value with no time-of-day and no time zone.
LocalTime for a time-of-day value without a date and without a time zone.
LocalDate startDate = LocalDate.parse( "2016-06-01" ); // Parsing ISO 8601 standard date format.
LocalTime startTime = LocalTime.MIN; // '00:00'.
Both of those classes can be used in factory methods to instantiate LocalDateTime and other classes.
LocalDateTime ldt = LocalDateTime.of( startDate , startTime );
In code above we used LocalTime.MIN to get 00:00. To directly answer your Question, you can also use LocalTime.MAX in the same way to get 23:59:59.999999999. But I do not recommend doing so. Read below about "Half-Open".
Time zone
Time zone is crucial in determining a date and a time. For any given moment the date and the hour-of-day both vary by time zone. A few minutes after midnight in Paris is a new day while still “yesterday” in Montréal.
The Local… types are not actual moments on the timeline. They represent a vague idea about possible moments. As noted above, the first moment of June 1st in Paris is simultaneously May 31st at 6 PM in Montréal. So before performing your database search you need to assign a time zone to your LocalDateTime. Applying a ZoneId produces a ZonedDateTime object.
Perhaps your date-time was intended to be Paris.
ZoneId zoneId = ZoneId.of( "Europe/Paris" );
ZonedDateTime zdt = ldt.atZone( zoneId );
Or perhaps you intended UTC. This all depends on your business rules, the context in which your app operates. For UTC, we use OffsetDateTime as UTC is not a full time zone but rather a mere offset-from-UTC. A time zone is an offset plus a set of rules for handling anomalies such as Daylight Saving Time (DST).
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC );
To get a string as asked for in the Question, extract LocalDate and call toString(). But I do not recommend this as it ignores time zone (read on down below).
String output = odt.toLocalDateTime.toString(); // Not likely to be what you really need.
Best practice in databases is to store the date-time in UTC. I don't know about MongoDB. Be sure to read the doc on how your database driver in Java may be affecting/translating the values you specify.
Start of Day
Be aware that a day does not always start at 00:00:00. In some time zones DST or other anomalies means the day may start at some other time such as 01:00.
The java.time classes will make adjustments as needed in some situations. Be sure to read the class doc so you see if the behavior matches your expectations & needs.
You can ask java.time to find the starting time.
ZonedDateTime zdt = LocalDate.of( "2016-06-01" ).atStartOfDay( zoneId );
Half-Open
Your attempt to determine the end of the day is a problem. That last second is infinitely divisible. Traditional Unix-oriented libraries resolve to whole seconds, the old date-time classes in Java resolve to milliseconds, some databases like Postgres may resolve to microseconds, and java.time and other databases such as H2 resolve to nanoseconds. Do not get in the middle of that.
Generally in date-time programming of a span of time, the best practice is "Half-Open". The beginning of the span is inclusive while the ending is exclusive.
So searching for a month of data in Paris zone means searching for records where the date-time is equal to or later than the start and less than (but not including) the stop.
ZoneId zoneId = ZoneId.of( "Europe/Paris" );
LocalDate startDate = LocalDate.of( "2016-06-01" );
ZonedDateTime zdt start = startDate.atStartOfDay( zoneId );
ZonedDateTime zdt stop = startDate.plusMonths(1).atStartOfDay( zoneId );
// Perform database search where ( ( x >= start ) AND ( x < stop ) ) . Notice '>=' versus '<' with no 'equals' on the latter.
Similarly, the month of records for UTC rather than Paris.
ZoneOffset zoneOffset = ZoneOffset.UTC;
LocalDate startDate = LocalDate.of( "2016-06-01" );
OffsetDateTime start = OffsetDateTime.of( startDate , zoneOffset );
OffsetDateTime stop = OffsetDateTime.plusMonths(1).of( startDate , zoneOffset );
// Perform database search where ( ( x >= start ) AND ( x < stop ) ) . Notice '>=' versus '<' with no 'equals' on the latter.
Using the Half-Open approach consistently throughout your app where handling spans of time will make your code more sensible and easier to understand. You can also train your users to think this way. We all use Half-Open intuitively in situations situations like "Lunch break is from 12:00 to 13:00". We all know this means be back from lunch before the clock strikes 13:00:00.0.
public class DateSample {
public static void main(String[] args) throws ParseException {
String startDate = "2016-06-01";
String endDate = "2016-07-01";
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date strDate = formatter.parse(startDate+" 00:00:00.000");
Date enDate = formatter.parse(endDate+" 23:59:59.999");
System.out.println(formatter.format(strDate));
System.out.println(formatter.format(enDate));
}
}
You will get
2016-06-01 00:00:00
2016-07-01 23:59:59
If you are running under jdk 1.8, use LocalDateTime
LocalDateTime is an embedded api of jdk 1.8. You can found explaination here docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html. You can use minus* or plus*, and parse methods

Cannot parse date string coming from MongoDB in Android/Java

I am trying to parse date (2015-06-25T00:00:00.000Z) coming from MongoDB.
try {
DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.ENGLISH);
Date date = format.parse("2015-06-25T00:00:00.000Z");
return new Date().after(date);
} catch (ParseException e) {
e.printStackTrace();
}
}
Where am I wrong?
Your pattern accepts only second digits but your string has fractional seconds as well
yyyy-MM-dd'T'HH:mm:ss 'Z'
2015-06-25 T 00:00:00.000 Z
You need to use
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
Do not ignore the Z
Your formatting pattern has single quote marks around the Z. That means to interpret the "Z" as mere text, to expect it but then ignore it. Very bad, as that Z has meaning: short for Zulu, and means UTC time zone.
By ignoring the Z, parsing will implicitly apply your JVM’s current default time zone. Your input meant the first moment of the day in UTC (stroke of midnight), but in the following code you can see the value is mis-interpreted as midnight in my default zone of America/Los_Angeles -- an error of 7 hours (my zone’s current offset from UTC).
try {
java.text.DateFormat format = new SimpleDateFormat ( "yyyy-MM-dd'T'HH:mm:ss'Z'" , Locale.ENGLISH );
java.util.Date date = format.parse ( "2015-06-25T00:00:00Z" );
System.out.println ( "date: " + date );
} catch ( ParseException e ) {
e.printStackTrace ();
}
In this output, PDT means the Daylight Saving Time (DST) version of Pacific time (more accurately named as America/Los_Angeles). Note the time is 00:00:00 but that is wrong -- should have been seven hours earlier on the previous day as my zone is behind UTC.
date: Thu Jun 25 00:00:00 PDT 2015
java.time
This work would be much easier with the java.time framework built into Java 8 and later. For Java 6 & 7, use the back-port, ThreeTen-Backport. For Android, the adaptation of that back-port, ThreeTenABP.
The java.time classes use ISO 8601 format by default when parsing/generating textual representations of date-time values. Your input happens to comply fully with ISO 8601. So no need to specify a formatting pattern.
An Instant is a moment on the timeline in UTC.
String input = "2015-06-25T00:00:00Z";
Instant instant = Instant.parse ( input );
Apply a proper time zone name if desired.
ZoneId zoneId = ZoneId.of ( "America/Los_Angeles" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
Dump to console.
System.out.println ( "input: " + input + " | instant: " + instant + " | zdt: " + zdt );
input: 2015-06-25T00:00:00Z | instant: 2015-06-25T00:00:00Z | zdt: 2015-06-24T17:00-07:00[America/Los_Angeles]
Note how in this output, the same input is now correctly adjusted to my America/Los_Angeles time zone by moving back seven hours into the previous date.
Convert to/from java.time
Avoid using java.util.Date. The old date-time classes really are that bad. But if required, you can convert between java.time types and the old types. In this case, by using the count-from-epoch in milliseconds. Be aware that you may lose a bit of data, going from the nanoseconds resolution to milliseconds in java.util.Date (not in this case, but perhaps in other cases).
java.util.Date utilDate = new java.util.Date( instant.toEpochMilli() );

How to convert UTC and local timezone in Java

I am curious about timezone in Java. I want to get UTC time in milliseconds from a device and send to server. Server will convert it to local timezone when it displays time to users. Timezone in my system is Australia/Sydney( UTC + 11:00), and I have got the result below when I tested timezone:
int year = 2014;
int month = 0;
int date = 14;
int hourOfDay = 11;
int minute = 12;
int second = 0;
Calendar c1 = Calendar.getInstance();
c1.set(year, month, date, hourOfDay, minute, second);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss z");
System.out.println(sdf.format(c1.getTime()));
Calendar c2 = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
c2.set(year, month, date, hourOfDay, minute, second);
System.out.println(sdf.format(c2.getTime()));
output:
14/01/2014 11:12:00 EST
14/01/2014 22:12:00 EST
I thought I could have 13/01/2014 00:12:00 for c2 because UTC time is 11 hours later than mine. Does not Calendar work the way I expect?
Your help would be appreciated.
EDIT
Added z to display timezone. This makes me more confused because Mac says its timezone is (AEDT) Australian Eastern Daylight Time but Java is EST. Anyway still result is different because EST is UTC-5 hours.
UPDATE: This Answer is now out-of-date. The Joda-Time library is now supplanted by the java.time framework built into Java 8 and later. See this new Answer.
Three-Letter Codes
You should avoid using 3 or 4 letter time zone codes such as EST or IST. They are neither standard nor unique.
Use proper time zone names, mostly Continent/CityOrRegion such as America/Montreal or Asia/Kolkata.
Joda-Time
The java.util.Date/Calendar classes are notoriously bad. Avoid using them. Use either Joda-Time or, in Java 8, the new java.time.* classes defined by JSR 310 and inspired by Joda-Time.
Notice how much simpler and more obvious is the Joda-Time code shown below. Joda-Time even knows how to count – January is 1, not 0!
Time Zone
In Joda-Time, a DateTime instance knows its own time zone.
Sydney Australia has a standard time of 10 hours ahead of UTC/GMT, and a Daylight Saving Time (DST) of 11 hours ahead. DST applies to the date specified by the question.
Tip: Don't think like this…
UTC time is 11 hours later than mine
Think like this…
Sydney DST is 11 hours ahead of UTC/GMT.
Date-time work becomes easier and less error-prone if you think, work, and store in UTC/GMT. Only convert to localized date-time for presentation in the user-interface. Think globally, display locally. Your users and your servers can easily move to other time zones, so forget about your own time zone. Always specify a time zone, never assume or rely on default.
Example Code
Here is some example code using Joda-Time 2.3 and Java 8.
// Better to specify a time zone explicitly than rely on default.
// Use time zone names, not 3-letter codes.
// This list is not quite up-to-date (read page for details): http://joda-time.sourceforge.net/timezones.html
DateTimeZone timeZone = DateTimeZone.forID("Australia/Sydney");
DateTime dateTime = new DateTime(2014, 1, 14, 11, 12, 0, timeZone);
DateTime dateTimeUtc = dateTime.toDateTime(DateTimeZone.UTC); // Built-in constant for UTC (no time zone offset).
Dump to console…
System.out.println("dateTime: " + dateTime);
System.out.println("dateTimeUtc: " + dateTimeUtc);
When run…
dateTime: 2014-01-14T11:12:00.000+11:00
dateTime in UTC: 2014-01-14T00:12:00.000Z
You probably meant to set the timezone on your formatter, not the Calendar (or in addition the the Calendar, it is not 100% clear what you mean to accomplish)! The timezone used to create the human representation comes from the SimpleDateFormat. All "timezone" information is lost from the Calendar when you convert it back into a java.util.Date by calling getTime().
The code:
Calendar c2 = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
c2.set(year, month, date, hourOfDay, minute, second);
System.out.println(sdf.format(c2.getTime()));
is printing 14/01/2014 10:12:00 because 11AM UTC displayed in Syndey (the timezone of your formatter) is 10PM! (use HH in the format for 24 hour time)
This would print what it seems like you meant to do:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy hh:mm:ss z");
System.out.println(sdf.format(c1.getTime()));
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(sdf.format(c1.getTime()));
The concept of 'UTC milliseconds' is meaningless. A quantity of milliseconds is just a fixed point in history, it has no timezone associated with it. We add a timezone to it to convert it into human-readable representations.
edit: Yes, the ambiguity of using 'EST' for both (US) Eastern Time and (Australian) Eastern Time has been a pitfall in Java since forever.
tl;dr
Use modern java.time classes.
ZonedDateTime
.of( 2014 , 1 , 14 , 11 , 12 , 0 , 0 , ZoneId.of( "Australia/Sydney" ) )
.toInstant()
.toEpochMilli()
1389658320000
Going the other direction.
Instant
.ofEpochMilli( 1_389_658_320_000L ) // .toString(): 2014-01-14T00:12:00Z
.atZone(
ZoneId.of( "Australia/Sydney" )
) // .toString(): 2014-01-14T11:12+11:00[Australia/Sydney]
.format(
DateTimeFormatter
.ofPattern (
"dd/MM/uuuu HH:mm:ss z" ,
new Locale( "en" , "AU" )
)
)
14/01/2014 11:12:00 AEDT
java.time
You are using terrible date-time classes that were made obsolete years ago by the adoption of JSR 310 defining the modern java.time classes.
I am curious about timezone in Java.
FYI, an offset-from-UTC is merely a number of hours-minutes-seconds. When we say “UTC” or put a Z at the end of a string, we mean an offset of zero hours-minutes-seconds, for UTC itself.
A time zone is much more. A time zone is a history of past, present, and future changes to the offset used by the people of a particular region. Politicians around the world have an odd penchant for changing the offset of their jurisdiction.
I want to get UTC time in milliseconds from a device and send to server.
For the current moment, use Instant. An Instant internally is the number of whole seconds seconds since the epoch reference of first moment of 1970 UTC, plus a fraction of a second in nanoseconds.
Instant now = Instant.now() ; // Capture current moment in UTC.
long millisecondsSinceEpoch = now.toEpochMilli() ;
Going the other direction.
Instant instant = Instant.ofEpochMilli( millisecondsSinceEpoch ) ;
Server will convert it to local timezone …
Specify the time zone desired/expected by the user.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument. If critical, confirm the zone with your user.
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( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
… when it displays time to users
Automatically localize for the user's language and culture.
To localize, specify:
FormatStyle to determine how long or abbreviated should the string be.
Locale to determine:
The human language for translation of name of day, name of month, and such.
The cultural norms deciding issues of abbreviation, capitalization, punctuation, separators, and such.
Example:
Locale l = Locale.CANADA_FRENCH ; // Or Locale.US, Locale.JAPAN, etc.
DateTimeFormatter f =
DateTimeFormatter
.ofLocalizedDateTime( FormatStyle.FULL )
.withLocale( l )
;
String output = zdt.format( f );
Timezone in my system is Australia/Sydney( UTC + 11:00)
The current default time zone of your server should be irrelevant to your program. Always specify the desired/expected time zone. Frankly, making optional the time zone (and Locale) argument of the various date-time methods is one of the very few design flaws in java.time framework.
Tip: Generally best to set your servers to UTC as their current default time zone.
By the way, be clear that time zone and locale have nothing to do with one another. You might want Japanese language for displaying a moment as seen in Africa/Tunis time zone.
ZoneID zAuSydney = ZoneId.of( "Australia/Sydney" ) ;
ZonedDateTime zdt = instant.atZone( zAuSydney ) ;
String output = zdt.format(
DateTimeFormatter
.localizedDateTime( FormatStyle.LONG )
.withLocale( new Locale( "en" , "AU" ) ;
) ;
int year = 2014; …
Note that java.time uses sane numbering, unlike the legacy classes. Months are 1-12 for January-December, and weekdays are 1-7 for Monday-Sunday.
LocalDate ld = LocalDate.of( 2014 , 1 , 14 ) ;
LocalTime lt = LocalTime.of( 11 , 12 ) ;
ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
zdt.toString() = 2014-01-14T11:12+11:00[Australia/Sydney]
Generally best to automatically localize for display, as seen above. But if you insist, you can hard-code a formatting pattern.
Locale locale = new Locale ( "en" , "AU" );
ZoneId z = ZoneId.of ( "Australia/Sydney" );
ZonedDateTime zdt = ZonedDateTime.of ( 2014 , 1 , 14 , 11 , 12 , 0 , 0 , z );
zdt.toString(): 2014-01-14T11:12+11:00[Australia/Sydney]
Specify that formatting pattern of yours.
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "dd/MM/uuuu HH:mm:ss z" , locale );
String output = zdt.format ( f );
output = 14/01/2014 11:12:00 AEDT
Your Question was interested in a count of milliseconds since epoch of 1970-01-01T00:00:00Z. So adjust from the Australia time zone to UTC. Same moment, same point on the timeline, different wall-clock time.
Instant instant = zdt.toInstant() ; // Adjust from time zone to UTC.
instant.toString(): 2014-01-14T00:12:00Z
Note the difference in hour-of-day between instant and zdt.
I thought I could have 13/01/2014 00:12:00 for c2 because UTC time is 11 hours later than mine.
➥ As you asked for, twelve minutes after 11 AM in Sydney zone is the same moment as twelve minutes after midnight in UTC, because Australia/Sydney on that date is eleven hours ahead of UTC.
Calculate milliseconds since epoch.
long millisecondsSinceEpoch = instant.toEpochMilli() ;
here is the output result you need to check this out
final String time="UTC";
int year = 2014;
int month = 0;
int date = 14;
int hourOfDay = 11;
int minute = 12;
int second = 0;
calendar.set(year, month, date, hourOfDay, minute, second);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSz");
System.out.println(sdf.format(calendar.getTime()));
Calendar calendar1=Calendar.getInstance();
Date dat= calendar.getTime();
calendar1.set(year,month,date,hourOfDay,minute,second);
sdf.setTimeZone(TimeZone.getTimeZone(time));
System.out.println(sdf.format(calendar1.getTime()));

Categories