I've tried a million different ways of doing this, but with no avail. Any help would be much appreciated.
long millis = getMillisFromServer();
Date date = new Date(millis);
DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
format.setTimeZone(TimeZone.getTimeZone("Australia/Sydney"));
String formatted = format.format(date);
The above doesn't work.
basically, what I want to do is, get the epoch time and convert it to Australian time. My local time is +05.30 but of course I don't want this to be a factor which contributes to this conversion.
EDIT-
Output when I run your exact code,
epoch 1318388699000
Wed Oct 12 08:34:59 GMT+05:30 2011
12/10/2011 03:04:59
12/10/2011 14:04:59
EDIT: Okay, so you don't want your local time (which isn't Australia) to contribute to the result, but instead the Australian time zone. Your existing code should be absolutely fine then, although Sydney is currently UTC+11, not UTC+10.. Short but complete test app:
import java.util.*;
import java.text.*;
public class Test {
public static void main(String[] args) throws InterruptedException {
Date date = new Date(1318386508000L);
DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String formatted = format.format(date);
System.out.println(formatted);
format.setTimeZone(TimeZone.getTimeZone("Australia/Sydney"));
formatted = format.format(date);
System.out.println(formatted);
}
}
Output:
12/10/2011 02:28:28
12/10/2011 13:28:28
I would also suggest you start using Joda Time which is simply a much nicer date/time API...
EDIT: Note that if your system doesn't know about the Australia/Sydney time zone, it would show UTC. For example, if I change the code about to use TimeZone.getTimeZone("blah/blah") it will show the UTC value twice. I suggest you print TimeZone.getTimeZone("Australia/Sydney").getDisplayName() and see what it says... and check your code for typos too :)
Here’s the modern answer (valid from 2014 and on). The accepted answer was a very fine answer in 2011. These days I recommend no one uses the Date, DateFormat and SimpleDateFormat classes. It all goes more natural with the modern Java date and time API.
To get a date-time object from your millis:
ZonedDateTime dateTime = Instant.ofEpochMilli(millis)
.atZone(ZoneId.of("Australia/Sydney"));
If millis equals 1318388699000L, this gives you 2011-10-12T14:04:59+11:00[Australia/Sydney]. Should the code in some strange way end up on a JVM that doesn’t know Australia/Sydney time zone, you can be sure to be notified through an exception.
If you want the date-time in your string format for presentation:
String formatted = dateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"));
Result:
12/10/2011 14:04:59
PS I don’t know what you mean by “The above doesn't work.” On my computer your code in the question too prints 12/10/2011 14:04:59.
Please take care that the epoch time is in second and Date object accepts Long value which is in milliseconds.
Hence you would have to multiply epoch value with 1000 to use it as long value .
Like below :-
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
sdf.setTimeZone(TimeZone.getTimeZone(timeZone));
Long dateLong=Long.parseLong(sdf.format(epoch*1000));
Related
I have a time in milliseconds: 1618274313.
When I convert it to time using this website: https://www.epochconverter.com/, I am getting 6:08:33 AM.
But when I use SimpleDateFormat, I am getting something different:
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
System.out.println(sdf.format(new Date(1618274313)));
I am getting output as 23:01:14.
What is the issue in my code?
In your example, you are using time 1618274313 and you are assuming that it is in milliseconds. However, when I entered the same time on https://www.epochconverter.com/, I got below results:
Please notice the site mentions: Assuming that this timestamp is in seconds.
Now if we use that number multiplied by 1000 (1618274313000) as the input so that the site considers it in milliseconds, we get below results:
Please notice the site now mentions: Assuming that this timestamp is in milliseconds.
Now, when you will use 1618274313000 (correct time in milliseconds) in Java with SimpleDateFormat, you should get your expected result (instead of 23:01:14):
SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
System.out.println(sdf.format(new Date(1618274313000)));
use Instant.ofEpochSecond
long test_timestamp = 1618274313L;
LocalDateTime triggerTime =
LocalDateTime.ofInstant(Instant.ofEpochSecond(test_timestamp),
TimeZone.getDefault().toZoneId());
System.out.println(triggerTime);
it prints output as 2021-04-13T06:08:33
Assuming it is in milliseconds as you say, all you know for certain is that you have a specific duration.
Duration d = Duration.ofMillis(1618274313);
System.out.println(d);
Prints
PT449H31M14.313S
Which says it is 449 hours, 31 minutes and 14.313 seconds of duration. Without knowing the epoch of this duration and any applicable zone offsets, it is not really possible to ascertain the specific date/time it represents. I could make lots of assumptions and provide results based on that, but more information from you would be helpful.
java.time
As Viral Lalakia already spotted, the epoch converter that you linked to, explicitly said that it assumed that the number was seconds (not milliseconds) since the epoch. The following makes the same assumption in Java. I recommend that you use java.time, the modern Java date and time API.
ZoneId zone = ZoneId.of("Asia/Kolkata");
long unixTimestamp = 1_618_274_313;
Instant when = Instant.ofEpochSecond(unixTimestamp);
ZonedDateTime dateTime = when.atZone(zone);
System.out.println(dateTime);
System.out.println(dateTime.format(DateTimeFormatter.ISO_LOCAL_TIME));
Output is:
2021-04-13T06:08:33+05:30[Asia/Kolkata]
06:08:33
This agrees with the 6:08:33 AM that you got from the converter. And the date is today’s date. A coincidence?
If the number is indeed milliseconds (which I honestly doubt), just use Instant.ofEpochMill() instead of Instant.ofEpochSecond().
Instant when = Instant.ofEpochMilli(unixTimestamp);
1970-01-19T23:01:14.313+05:30[Asia/Kolkata]
23:01:14.313
This in turn agrees with the result you got in Java (except that the milliseconds are also printed).
I'm working on an app where users can timestamp themselves IN or OUT from their workplace. At the moment I'm trying to get the localization of the timestamps done. For example when I make a timestamp in UTC +02:00 at 08:00 02.01.2020, it works correctly and shows the time as 08:00 and right date as well. But when I change to UTC +01:00 in my phone settings, and do the same timestamp, the time becomes 07:00 and date becomes 01.01.2020.
The code I have so far for "parsing" the time looks like this:
String formattedTime = "";
String datetime2 = "1970-01-01T" + returntime;
Log.v("DATE", datetime2);
OffsetDateTime odt2 = OffsetDateTime.parse(datetime2);
Date date2 = Date.from(odt2.toInstant());
SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm",Locale.getDefault());
formattedTime = sdf2.format(date2);
Log.v("FORMTIME", formattedTime);
I'm using a similar code snippet for "parsing" the date as well.
The output for the two logs (when in UTC +01:00):
V/DATE: 1970-01-01T15:00:00+02:00
V/FORMTIME: 14:00 //SHOULD BE 15:00
V/DATE: 1970-01-01T08:00:00+02:00
V/FORMTIME: 07:00 //SHOULD BE 08:00
V/DATE: 1970-01-01T08:00:00+02:00
V/FORMTIME: 07:00 //SHOULD BE 08:00
It seems like the change in UTC from +02:00 to +01:00 reduce the time and date also with 1...
So is it wrong to use the OffsetDateTime class and "toInstant" (Instant class) for what I'm trying to achieve? What would be the right solution?
OffsetTime
I don’t understand what that offset of +02:00 in your string signifies. In particular it confuses me what you want to do when the offset changes. In any case java.time, the modern Java date and time API, parses and formats your time pretty easily. Let’s first define the formatter that describes your desired output format:
private static final DateTimeFormatter timeFormatter
= DateTimeFormatter.ofPattern("HH:mm");
With this in place you may do:
String returntime = "15:00:00+02:00";
OffsetTime time = OffsetTime.parse(returntime);
String formattedTime = time.format(timeFormatter);
System.out.println(formattedTime);
Output:
15:00
The offset is parsed, but is not used for anything. The output time will always be the same as the time in the string.
I take it that the date 1970-01-01 that you used in your code is arbitrary and without significance. The OffsetTime that I am using hasn’t got a date, so saves us from choosing a date for processing the time.
Word use: There isn’t any localization going on here. Localization is when for an American audience you print 3:00 PM instead of 15:00, for example.
EDIT:
If your string contains a date too, OffsetDateTime is the right class to use, and again we need no explicit formatter for parsing (only for formatting). Your code in the comment is fine (except that you had accidentally reversed the order of day, month and year in the string).
String returnDate1 = "2020-12-05T00:00+02:00";
DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
OffsetDateTime dateTime = OffsetDateTime.parse(returnDate1);
String formattedDate = dateTime.format(dateFormatter);
System.out.println(formattedDate);
05-12-2020
What went wrong in your code?
It seems you were over-complicating things. In particular you were mixing old and modern date-time classes. The old ones, Date and SimpleDateFormat, are poorly and confusingly designed, which no doubt contributed to your unexpected results. And when mixing, you are going to need conversions that are not really needed for your job, again just making your code more complicated than needed.
Your sdf2 was using your default time zone for printing the time. You had got offset +02:00 in the string, so when you set the phone to UTC+01:00, a conversion takes place. When the time is 08:00 at offset +02:00, it is only 07:00 at offset +01:00. So this was the result you got. This in turn means that if the user’s time zone was at offset +01:00 on 1970-01-01, then you were getting the correct times for that time zone.
I have date 2015-12-25 23:59:59 in the form of epoch milliseconds 1451087999000, And I want the date part only i.e. 2015/12/25, how do I do that efficiently might be with the JODA time library which is nowdays standard for dealing with Date time in java.
I have this code which works in most the case but when time is like 23:59:59 it gives me the next date (as in my case it gives 2015-12-26 with input of 2015-12-25 23:59:59)-
String dateInMilliSeconds = "1451087999000";
String dateInYYYYMMDDFormat = DateHelper.convertDateFormat(new Date(Long.valueOf(dateInMilliSeconds)),DateHelper.yyyy_MM_dd);
DateHelper.convertDateFormat() -
public static final String yyyy_MM_dd = "yyyy-MM-dd";
public static String convertDateFormat( Date date, String outputFormat )
{
String returnDate = "";
if( null != date )
{
SimpleDateFormat formatter = new SimpleDateFormat(outputFormat);
returnDate = formatter.format(date);
}
return returnDate;
}
You can use localDate from java 8
LocalDate date = Instant.ofEpochMilli(dateInMilliSeconds).atZone(ZoneId.of(timeZone)).toLocalDate();
I should like to make two points:
Time zone is crucial.
Skip the outdated classes Date and SimpleDateFormat.
My suggestion is:
String dateInMilliSeconds = "1451087999000";
LocalDate date = Instant.ofEpochMilli(Long.parseLong(dateInMilliSeconds))
.atOffset(ZoneOffset.UTC)
.toLocalDate();
System.out.println(date);
This prints
2015-12-25
Please note that you get your desired output format for free: LocalDate.toString() produces it. If you want to be able to produce different output formats, use a DateTimeFormatter.
Time zone
Your millisecond value isn’t just equal to 2015-12-25 23:59:59. It is equal to this date and time in UTC, so you need to make sure that your conversion uses this time zone offset. When I run your code from the question on my computer, I incorrectly get 2015-12-26 because my computer is in the Europe/Copenhagen time zone.
JSR-310 AKA java.time
Joda-Time was the widely acknowledged better alternative to the original date and time API from Java 1 that many considered poor and troublesome. The Joda-Time project is now finished because the modern Java date and time API known as JSR-310 or java.time came out three and a half years ago, so they recommend we use this instead. So my code does.
The timestamp 1451087999000 is 2015-12-25 23:59:59 in UTC. In your code, you're not specifying the timezone when you format it with a SimpleDateFormat, so it's formatted in your local timezone.
With Joda Time:
String dateInMilliSeconds = "1451087999000";
LocalDate date = new LocalDate(Long.parseLong(dateInMilliSeconds), DateTimeZone.UTC);
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd");
String result = formatter.print(date);
In my app, I am using SimpleDateFormat to convert the Date object to a string. But sometime when I change the time zone one by one to test whether the date I enter is the same as the date converted to a string, I found that it shows a different date. For example, suppose I have Thu Mar 15 00:00:00 GMT+08:00 2012 in my Date object, Now when I convert it to a string using SimpleDateFormat it works fine, but when I change the time zone one by one and check whether the date converted to string is same as it stored in Date object then in some cases it shows as 14-Mar-2012 instead of showing 15-Mar-2012. Why this happen? Can anyone please suggest me how to solve this out?
Code I have used:
SimpleDateFormat m_sdFormatter = new SimpleDateFormat("dd-MMM-yyyy");
String selected_date = m_sdFormatter.format(btnSelectedDt.getTime());
try this ,hope it may help you..
private String getDate(long timeStamp) {
DateFormat objFormatter = new SimpleDateFormat("dd-MM-yyyy");
objFormatter.setTimeZone(TimeZone.getDefault());
Calendar objCalendar = Calendar.getInstance(TimeZone.getDefault());
objCalendar.setTimeInMillis(timeStamp * 1000);
String result = objFormatter.format(objCalendar.getTime());
objCalendar.clear();
return result;
}
For example suppose i have Thu Mar 15 00:00:00 GMT+08:00 2012 in my Date object,
You haven't got that (even though that's no doubt what toString displays). A Date object doesn't contain a time zone. It contains an instant in time, which can be interpreted as different dates and times based on the calendar and time zone you use to interpret it. So that's midnight in once specific time zone - but the Date object itself is just a number of milliseconds since the unix epoch.
It's not clear exactly what you're doing, but you shouldn't be surprised that changing the time zone used in SimpleDateFormat will change the date written out. If you can describe in more detail what the larger goal is, we may be able to help you more. Note that if you can use Joda Time instead, that's a much better date/time API - but I know that it's quite large for use in an Android app.
In your SimpleDateFormat, mention the locale,
DateFormat objFormatter = new SimpleDateFormat("dd-MM-yyyy", locale);
where locale is of your choice. For eg, I use Locale.ENGLISH as it contains the date format that I require. Otherwise when you change ure locale in the device, the simpledateformat changes to current locale and you end up getting the wrong date.
I have seconds like below:
1320130800
I need to convert the value into Date and Time Combination format. While formatting I got the result as follows:
Tuesday,November 1,2011 2:00,AM
But the correct result is as follows:
Tuesday,November 1,2011 7:00,AM
For the above format conversion I used the below code:
long millis = 1320130800*1000;
Date date = new Date(millis);
SimpleDateFormat sdf = new SimpleDateFormat("EEEE,MMMM d,yyyy h:mm a");
String formattedDate = sdf.format(date);
System.out.println(formattedDate);
Can any one guide me to get the correct answer?
Sounds like it's just a time zone issue - you need to set the time zone for the formatter:
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
(Note that in your sample code, long millis = 1320130800*1000; doesn't work as it performs the multiplication in 32-bit arithmetic; you need something like long millis = 1320130800L*1000;.)
Use the Calendar API instead.
After you have the Date object, construct a Calendar object (getInstance() returns one with the default Time Zone) and do setDate(Date) on it and parse it like that.
Alternatively, you can take a look at Joda Time APIs since they are easy to use.
Regards!