Converting a Joda DateTime to another timezone without changing the time - java

I have tried all the ways in all the other questions on SO, and I can't get it to work. It is making me want to kill myself.
I have a set of times which are something like "04:00 AM AEST", except the AEST is a glitch, they should be GMT. What I want to do is change them to "04:00 GMT", and then convert them up to the correct AEST times (which in this example would be "14:00 AEST"). I have tried everything, and nothing works. The closest was to manually make a new DateTime using each individual value from the original date, e.g.
DateTime dt = new DateTime(origdate.year, origdate.month, origdate.day, origdate.hour, origdate.minute, origdate.second, timezone.GMT)
But for some reason the results came out four and a half minutes over, which is weird because timezones differ on hours and half hours.

1st Method By following lines you will get GMT time in specified format :
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
Date currentLocalTime = cal.getTime();
DateFormat date = new SimpleDateFormat("dd-MM-yyy HH:mm:ss z");
date.setTimeZone(TimeZone.getTimeZone("GMT"));
String gmtTime = date.format(currentLocalTime);
Hence, from GMT you can derive the time of any place.
2nd Method You can get system time of current place in milliseconds by:
Long current_time = System.currentTimeMillis() / 1000L;
Hope it helps.

Related

Having problems on getting actual time in UTC Android

I am trying to get the the day and time in UTC as milliseconds but repeatedly get the same problem. The result should be something like '63530139420000' but each time the value '1394547490884' is returned.
To get the date and time in UTC I use the following method:
long dateutc = System.currentTimeMillis();
Can anyone tell me what is the problem?
You can use this.
DateFormat df = DateFormat.getTimeInstance();
df.setTimeZone(TimeZone.getTimeZone("UTC"));
String dateutc = df.format(new Date());
Your code correctly gets the number of milliseconds since January 1, 1970 00:00:00 UTC.
Interestingly if you take the value your teacher has specified and divide by the number of milliseconds in a year you get 2014.5. So either your teacher doesn't know what currentTimeMillis() does or he wants milliseconds since year 0 (which doesn't make any sense to me).
To calculate number of milliseconds since a given date all you need to do is to create two date instances and subtract the milliseconds values from getTime().

Ignoring DST when using Java Calendars

I have a GUI that plots time-series graphs. The user enters the dates they want to plot from and to by entering values in text boxes. For example, if they enter 25/07/13 22:00 and 26/07/13 00:00 the graph should plot data from 22:00:00 on the 25th through to 00:00:59 the following morning. The times the user enters are parsed into a Calendar object.
My problem comes with DST.
The user doesn't care about DST, so all they want to see is a graph between those two times. However, the Calendar objects do care about DST and so my "to" date is currently not 00:00, but 01:00. (I am in London and we are currently GMT + 1 hour for DST).
I want to effectively ignore DST and act as though everything is GMT + 0 when I want to plot graphs.
How can I do this?
Thanks for the answers guys, they helped me get my head around the problem. It sort of comes down to the fact that I use both the Calendar object, for presentation and storage of data, and the epoch for temporal calculations.
It turns out that the Calendar set() methods will take into account DST as a matter of course. So when I parse the time values in the text boxes that the user enters, and use set() for each individual Calendar field, the Calendar object will know, based-off historical data, whether the date you've just set will have DST applied. Because of this, it understands that you meant, for example, GMT+1, even if you didn't realise it (because, frankly, who does?!).
However, when you do getTimeInMillis(), the epoch returned has no concept of time zones or DST, so to match with the current time zone you have to apply DST manually to the returned epoch, if it applies. Conversely, when you use setTimeInMillis() on a Calendar object, it is assumed that the time you entered is GMT+0, but if the epoch is a date that currently has DST applied, the Calendar object will add it on for you, meaning you're +1 hour from where you thought you were. To solve this problem, you need to subtract DST, again if necessary, from the epoch before setting it in the calendar.
All of this confusion is particularly important on day boundaries, especially if you're using day resolution for anything, like me.
Calendar calendar = Calendar.getInstance();
calendar.set(calendar.DST_OFFSET, 0);
If I understand you correctly you need to parse 25/07/13 22:00 as GMT date/time:
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy HH:mm");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Date date = sdf.parse("25/07/13 22:00");
and make a Calendar based on this date
Calendar c= Calendar.getInstance();
c.setTime(date);
TimeZone tz = TimeZone.getTimeZone("Etc/GMT0");
DateFormat df = DateFormat.getDateTimeInstance();
df.setTimeZone(tz);
System.out.println(df.format(new Date()));

Java Timezone: why Offset is needed

My requirment is like this:
I am saving time in millisecond in database and the timezone.For example the time in milisecond is 1223123123232 in long and timezone is Asia/Calcutta. I have to convert it to Africa/Asmara timezone.
long l = 1223123123232l;
TimeZone tz = TimeZone.getTimeZone("Asia/Calcutta");
long tzOff = tz.getOffset(l);
java.util.Date d = new Date(l-tzOff); // WHY THIS??
DateFormat df = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
df.setTimeZone(TimeZone.getTimeZone("Africa/Asmara"));// required timezone
String s = df.format(d);
System.out.println(s);
To check i am refering this: link
My question is:
If the timezone is just the representation of time in different formats(geographical areas offset from GMT),why do i need to subtract the offset time form the actual time (l-tzOff)?
Why can't i ignore the timezone which is saved in Database, and only consider the timezome in which i want to convert the date?
Something like:
long l = 1223123123232l;
java.util.Date d = new Date(l);
DateFormat df = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
df.setTimeZone(TimeZone.getTimeZone("Africa/Asmara"));// required timezone
String s = df.format(d);
System.out.println(s);
My system timezone is Asia/Calcutta, i want to convert a Date in Africa/Bujumbura timezone to Europe/Vatican timezone.The above code is not working in this case? Why this is so?
Java dates do not know about time zones. Therefore, if I save 14H00 in New-York, it will not be the same 14H00 as in Paris, although the millisecond value is the same. You need to use a unique reference to save dates. People often chose GMT+0.
If you need to check local time across timezones, you can use a tool I developed here.
To answer your questions:
Timezone is not a representation of time, it is a localisation of time. The reason you would substract an offset is to make sure all time is defined according to the same reference.
Because you would get false results and false dates.
new Date(long) takes the number of milliseconds since the GMT epoch. Since in your case l is the number of milliseconds since some other point in time (namely 1 Jan 1970, 00:00:00 in Asia/Calcutta), you have to convert it to GMT first. This is done by subtracting the relevant timezone offset.

Performing date and time calculations in Java

I'm trying to do simple date/time calculations and no matter what I do I'm getting confused with what appears to be time zones etc.
I need to add (and subtract)different date/times together so I figured the easiest way would be to convert them to seconds, perform the calculations and then format back to a string. But no matter what I do, I'm one hour out - which sounds like timezone/DST etc.
What's wrong with this:
long dateInMillis = 3600000L;
DateFormat formatter = new SimpleDateFormat("HH:mm");
Date dt = new Date();
dt.setTime(dateInMillis);
System.out.println( formatter.format(dt.getTime()));
The answer I get is 2:00. Even if I use:
long dateInMillis = 1;
I still get 1:00
Help please ;-)
TIA
Martin
I agree that using Joda is likely to make life easier. However what you are seeing is the effect of a TimeZone sensitive formatter.
You could try adding:
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
Save yourself a lot of headache, use an existing library for this - I like Joda Time myself.
For example the DateTime class supports various calculations (to add or subtract specific periods etc.) If you want an example, post your exact requirement, and I'll add it to the answer.
You should not try and format a long as a date. Just use:
long dateInMillis = 3600000L;
DateFormat formatter = new SimpleDateFormat("HH:mm");
Date dt = new Date();
dt.setTime(dateInMillis);
System.out.println( formatter.format(dt));
However, I would use a 3rd party lib for handling time-calculations like JodaTime as #Nim suggested, if your calculations are in anyway complicated.
I also suggest to use a framework as suggested in the comments.
However, Date is based on the milliseconds after Jan. 1st 1970. So 3600000L is just one hour from there, so 1:00 is correct.
According to people here, you could use Joda Time to resolve this calculations. If you want to stay with pure Java code, you can look for Calendar class to do your operations with dates. Here is a sample:
Calendar c = Calendar.getInstance();
DateFormat df = new SimpleDateFormat("HH:mm");
Date d = c.getTime();
System.out.println(df.format(d)); //actual hour:minute
c.add(Calendar.HOUR, -4);
d = c.getTime();
System.out.println(df.format(d)); //actual hour:minute minus 4 hours
Still, I won't rely too much in this kind of code. You'll have less problems using Joda Time.
When you're calling new Date(), current date in current timezone is created. When you're calling 'dt.setTime(dateInMillis);' you set offset in milliseconds from 1 January 1970 in GMT timezone. Let me explain, here in Msk, first call will give me Thu Mar 01 17:02:22 MSK 2012, the second call will give me 1 hour offset, thus in Msk it will be original offset (+3) plus 1, so it'll be Thu Jan 01 04:00:00 MSK 1970. Then when you're calling formatter.format(? extends Number) it calls new Date(((Number)obj).longValue()) inside, so it creates back you date which is Thu Jan 01 04:00:00 MSK 1970 and prints hours and minutes. So, you're right, it prints out time in your current timezone.
For posterity, here's example code using the Joda-Time 2.3 library as mentioned by the other answers and comments.
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
long dateTimeInMillis = 3600000L; // 1,000 * 60 * 60 = 3600000L = 1 hour.
// Time Zone list… http://joda-time.sourceforge.net/timezones.html (not quite up-to-date, read page for details)
DateTime dateTimeInUtc = new DateTime( dateTimeInMillis, DateTimeZone.UTC );
// Paris happens to be one hour ahead of UTC/GMT.
DateTime dateTimeInParis = dateTimeInUtc.toDateTime( DateTimeZone.forID( "Europe/Paris" ) );
Dump to console…
System.out.println( "dateTimeInUtc: " + dateTimeInUtc );
System.out.println( "dateTimeInParis: " + dateTimeInParis );
When run…
dateTimeInUtc: 1970-01-01T01:00:00.000Z
dateTimeInParis: 1970-01-01T02:00:00.000+01:00

How can I print a Date without timezone?

I have a mobile application where I capture a date/time and send it as miliseconds to a servlet. -For example I capture 12:55 AM in my cellphone and send it to my server-
So, I construct the date from the sent miliseconds and print it with SimpleDateFormat but the time is diferent, it prints 8:55 AM.
I know that the problem is because I use 2 diferent timezones, my question is:
how can I show that time without apply any timezone to show the same time?
Thanks in advance
You need to use Calendar to change the TimeZone but there is no API for that.
// Change a date in another timezone
public static Date changeTimeZone(Date date, TimeZone zone) {
Calendar first = Calendar.getInstance(zone);
first.setTimeInMillis(date.getTime());
Calendar output = Calendar.getInstance();
output.set(Calendar.YEAR, first.get(Calendar.YEAR));
output.set(Calendar.MONTH, first.get(Calendar.MONTH));
output.set(Calendar.DAY_OF_MONTH, first.get(Calendar.DAY_OF_MONTH));
output.set(Calendar.HOUR_OF_DAY, first.get(Calendar.HOUR_OF_DAY));
output.set(Calendar.MINUTE, first.get(Calendar.MINUTE));
output.set(Calendar.SECOND, first.get(Calendar.SECOND));
output.set(Calendar.MILLISECOND, first.get(Calendar.MILLISECOND));
return output.getTime();
}
Link: http://blog.vinodsingh.com/2009/03/date-and-timezone-in-java.html
I think this should work. I haven't extensively tested it.
Calendar and Date objects store their date information in milliseconds in relation to UTC.
(the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC)
This means that Calendar/Date Objects do not store different values for different Time Zones. They always use the same value internally... the format is what normally changes.
Maybe you can use a SimpleDateFormat in your local/default timezone:
SimpleDateFormat sdf = new SimpleDateFormat("S")
Date d = sdf.parse(milliseconds);
You can also try to change the DateFormat's timezone until it matches your expected output.
sdf.setTimeZone(TimeZone.getTimeZone("GMT-8"));
System.out.println(sdf.toString());
sdf.setTimeZone(TimeZone.getTimeZone("GMT-4"));
System.out.println(sdf.toString());

Categories

Resources