Converting local timestamp to UTC timestamp in Java - java

I have a milliseconds-since-local-epoch timestamp that I'd like to convert into a milliseconds-since-UTC-epoch timestamp. From a quick glance through the docs it looks like something like this would work:
int offset = TimeZone.getDefault().getRawOffset();
long newTime = oldTime - offset;
Is there a better way to do this?

Sadly, this seems to be the best way to do this:
public static Date convertLocalTimestamp(long millis)
{
TimeZone tz = TimeZone.getDefault();
Calendar c = Calendar.getInstance(tz);
long localMillis = millis;
int offset, time;
c.set(1970, Calendar.JANUARY, 1, 0, 0, 0);
// Add milliseconds
while (localMillis > Integer.MAX_VALUE)
{
c.add(Calendar.MILLISECOND, Integer.MAX_VALUE);
localMillis -= Integer.MAX_VALUE;
}
c.add(Calendar.MILLISECOND, (int)localMillis);
// Stupidly, the Calendar will give us the wrong result if we use getTime() directly.
// Instead, we calculate the offset and do the math ourselves.
time = c.get(Calendar.MILLISECOND);
time += c.get(Calendar.SECOND) * 1000;
time += c.get(Calendar.MINUTE) * 60 * 1000;
time += c.get(Calendar.HOUR_OF_DAY) * 60 * 60 * 1000;
offset = tz.getOffset(c.get(Calendar.ERA), c.get(Calendar.YEAR), c.get(Calendar.MONTH), c.get(Calendar.DAY_OF_MONTH), c.get(Calendar.DAY_OF_WEEK), time);
return new Date(millis - offset);
}
(I know that this is several months past post date, but it's a problem that is very useful to solve when working with text messages on Android. dave's answer is wrong.)

Use a Calendar to get what the offset was at the local Epoch, then add that to the local-epoch timestamp.
public static long getLocalToUtcDelta() {
Calendar local = Calendar.getInstance();
local.clear();
local.set(1970, Calendar.JANUARY, 1, 0, 0, 0);
return local.getTimeInMillis();
}
public static long converLocalTimeToUtcTime(long timeSinceLocalEpoch) {
return timeSinceLocalEpoch + getLocalToUtcDelta();
}

Using Joda Time it would be like this :
DateTime dt = new DateTime(year, month, day, hour, minute, 0, 0, DateTimeZone.forID("local");
dt.getMillis();
EDITED: Sorry, this is the correct version :
DateTime dt = new DateTime(timestamp, DateTimeZone.forID("local");
dt.getMillis();

Actually, Chris Lercher hit the nail on the head, but he only made it in a short comment, so I wanted to expand on it.
Imagine two stopwatches; one is somewhere where UTC is the local time on Jan 1, 1970, and the other stopwatch is local to your area (let's say that it's in New York, 5 hours after UTC). At UTC midnight, on Jan 1, 1970, the UTC stopwatch is started. 5 hours later, your local stopwatch is started. Those two stopwatch times differ by some amount, determined only by what the difference between UTC was from your local time at local midnight on Jan 1, 1970. Any daylight-saving shenanigans, since then, have no bearing on the difference between those stopwatches. So, any DST corrections for your present time or for the times you're converting, are irrelevant. All you need is how much later your local stopwatch started on Jan 1, 1970.
As Chris pointed out, this is just: getOffset(0L), so:
int offset = TimeZone.getDefault().getOffset(0L);
long newTime = oldTime - offset;
... should work fine. However....
To help really grasp this, note this: that "0L" in getOffset() is the milliseconds since the UTC epoch (which is the only real epoch). So, your offset variable is going to have the number of seconds of offset at midnight UTC (ie, when it was, say, 19:00 on 12/31/1969 in New York). If your local time switched to/from daylight-saving in those last hours before local midnight, then getOffset(0L) wouldn't be correct. You need to know what your daylight-saving status was at local midnight, not UTC's midnight.
I'd be surprised if this were the case, anywhere (ie, any timezone which changed to/from DST between their local midnight and UTC midnight of Jan 1, 1970). However, just for fun, a cheap hack to help guard against this would be to check if the offset changed in those hours:
// Offset at UTC midnight
int offset = TimeZone.getDefault().getOffset(0L);
long newTime = oldTime - offset;
// Offset at Local midnight
int localMidnightOffset = TimeZone.getDefault().getOffset(-offset);
Here, localMidnightOffset will be what the timezone offset was at a time -offset milliseconds after UTC midnight in 1970. If no DST change happened, then localMidnightOffset will equal offset, and you're done. If some DST change did occur, then you might have to hunt around... probably keep doing a
localMidnightOffset = TimeZone.getDefault().getOffset(-localMidnightOffset)
until it stops changing... and hope you don't get caught in an endless loop. I'm curious to see if anybody has a guaranteed-converging solution.
Kinda makes you wish the world were flat, huh?

No, that definitely won't work - it doesn't take DST into account. You can't just use getOffset(oldTime) either, as the DST may have changed between the two...
You could use getOffset(oldTime) to get an initial guess at the timestamp, then check getOffset(utcTime) to see whether they're the same or not. It gets fun, basically.
Joda Time should support this using DateTimeZone.getOffsetFromLocal but that's slightly broken (IMO) around DST transitions.
All of this really depends on what you mean by "milliseconds since local epoch". If you really mean elapsed milliseconds since local 1970, you could just find out the offset at that date, and apply that regardless. Typically (IME) a "local" millis value doesn't mean quite that though - it means "the number of millis to get to a particular date and time (e.g. April 9th 2010, 18:06pm) in UTC, but in respect of a different time zone". In other words, it can represent ambiguous or impossible date/time combinations based on DST transitions.

static final long localTimeZoneoffset = TimeZone.getDefault().getOffset(0L);
static final long dstOffset = TimeZone.getDefault().getDSTSavings();
long offsetOftime = TimeZone.getDefault().getOffset(time.getTime());
long timeinmilli = 0L;
if(offsetOftime != localTimeZoneoffset)
timeinmilli = time.getTime()+localTimeZoneoffset+dstOffset;
else
timeinmilli = time.getTime()+localTimeZoneoffset;
return new Timestamp(timeinmilli);
This worked for me to convert to UTC.

May be this can help you i have try this way. Please comment me if there is any best and optimize way to convert local time to UTC timestamp.
String mDate= "Jul 21,2016 1:23 PM";
String mDateFormat =""MMM d,yyyy h:mm a";
Call : getConvertedTimeToUTC(mDate,mDateFormat);
public String getConvertedTimeToUTC(String ourDate, String mDateFormat) {
try {
SimpleDateFormat fmt = new SimpleDateFormat(mDateFormat);
fmt.setTimeZone(TimeZone.getTimeZone("UTC"));
Date value = fmt.parse(ourDate);
if (value != null)
return String.valueOf(value.getTime() / 1000);
else
return null;
} catch (Exception e) {
ourDate = "00-00-0000 00:00";
}
return ourDate;
}
Here is the result : (Ref : check conversion)
Result 1469107380
GMT: Thu, 21 Jul 2016 13:23:00 GMT
Your time zone: Thursday 21 July 2016 06:53:00 PM IST GMT+5:30

Related

Joda-time off-by-one error when counting days after 1918-03-24

Calculating the number of days between 1900-01-01 and a date after 1918-03-24 using Joda-Time seems to give an off-by-one result.
Using Java 8 java.time gives the correct result. What is the reason for Joda-Time not counting 1918-03-25?
Using Joda-time v2.9.9.
public static void main(String[] args) {
jodaDiff("1918-03-24");
javaDiff("1918-03-24");
jodaDiff("1918-03-25");
javaDiff("1918-03-25");
jodaDiff("1918-03-26");
javaDiff("1918-03-26");
jodaDiff("2017-10-10");
javaDiff("2017-10-10");
}
private static void jodaDiff(String date) {
DateTime start = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeZone.forID("UTC"));
DateTimeFormatter dateDecoder = DateTimeFormat.forPattern("YYYY-MM-dd");
DateTime end = dateDecoder.parseDateTime(date);
int diff = Days.daysBetween(start, end).getDays();
System.out.println("Joda " + date + " " + diff);
}
private static void javaDiff(String date) {
LocalDate start = LocalDate.parse("1900-01-01");
LocalDate end = LocalDate.parse(date);
int diff = (int) ChronoUnit.DAYS.between(start, end);
System.out.println("Java " + date + " " + diff + "\n");
}
Output:
Joda 1918-03-24 6656
Java 1918-03-24 6656
Joda 1918-03-25 6656
Java 1918-03-25 6657
Joda 1918-03-26 6657
Java 1918-03-26 6658
Joda 2017-10-10 43015
Java 2017-10-10 43016
The problem is that your DateTimeFormatter is using the system default time zone. Ideally, you should parse to LocalDate values instead of DateTime, but you can fix it by using UTC for the formatter anyway:
DateTimeFormatter dateDecoder = DateTimeFormat.forPattern("YYYY-MM-dd").withZoneUTC();
To parse with LocalDate instead, just use:
org.joda.time.LocalDate start = new org.joda.time.LocalDate(1900, 1, 1);
DateTimeFormatter dateDecoder = DateTimeFormat.forPattern("YYYY-MM-dd");
org.joda.time.LocalDate end = dateDecoder.parseLocalDate(date);
(Obviously you don't need to fully-qualify it if you're not using Java 8.)
#Jon Skeet's answer is correct and direct to the point. I'd just like to add more details about what's happening and why you get these results (as you asked in the comments - and Jon also replied with a hint, that's also correct).
Your JVM default timezone is probably Europe/London (or any other that has a DST change in March 24th 1918). You can check that by using DateTimeZone.getDefault() in Joda-Time and ZoneId.systemDefault() in Java 8.
The start date you created in Joda is 1900-01-01T00:00Z (January 1st 1900 at midnight in UTC). The end date, though, is created only by using the year, month and day. But the DateTime also needs the time (hour/minute/second/millisecond) and a timezone. As those are not specified, it's set to midnight at the JVM default timezone (which is not guaranteed to be UTC - depending on the JVM configuration, you can get a different result).
Assuming your default timezone is London (that's how I could reproduce the problem - in my JVM default timezone (America/Sao_Paulo) it doesn't happen).
In March 25th 1981, London was in DST, so when you create your end date with 1918-03-25, the result is March 25th 1981 at midnight in London timezone - but due to DST change, the result is 1918-03-25T00:00+01:00 - during DST, London uses the offset +01:00, which means it's one hour ahead of UTC (so this end date is equivalent to 1918-03-24T23:00Z - or March 24th 1981 at 11 PM in UTC).
So, the difference in hours is 159767, which is not enough to complete 6657 days, so the difference is 6656 days (the rounding is always to the lowest value - the difference must be at least 159768 hours to complete 6657 days).
When you use a LocalDate, though, the time and DST effects are not considered (a LocalDate has only day, month and year), and you get the correct difference. If you set the end date to UTC, as well, you also get the correct results because UTC doesn't have DST changes.
By the way, if you use Java 8 ZonedDateTime, and use the start date with UTC and end date with London timezone (instead of using a LocalDate), you get the same difference in the results.
Not directly related, but in Joda-Time you can use the constant DateTimeZone.UTC to refer to UTC - calling forID("UTC") is redundant, as it returns the constant anyway (DateTimeZone.forID("UTC")==DateTimeZone.UTC returns true).
Joda-time off-by-one error when counting days after 1918-03-24
Try this, I corrected your program It gives you excepted answer with comparison with Java
public static void main(String[] args) {
jodaDiff("1918-03-24");
javaDiff("1918-03-24");
jodaDiff("1918-03-25");
javaDiff("1918-03-25");
jodaDiff("1918-03-26");
javaDiff("1918-03-26");
jodaDiff("2017-10-10");
javaDiff("2017-10-10");
}
private static void jodaDiff(String date) {
DateTime start = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeZone.forID("UTC"));
DateTime end = new DateTime(date);
int diff = Days.daysBetween(start.toLocalDate(), end.toLocalDate()).getDays();
System.out.println("Joda " + date + " " + diff);
}
private static void javaDiff(String date) {
LocalDate start = LocalDate.parse("1900-01-01");
LocalDate end = LocalDate.parse(date);
int diff = (int) ChronoUnit.DAYS.between(start, end);
System.out.println("Java " + date + " " + diff + "\n");
}
DateTime start = new DateTime(1900, 1, 1, 0, 0, 0, DateTimeZone.forID("UTC"));
DateTimeFormatter dateDecoder = DateTimeFormat.forPattern("YYYY-MM-dd").withZone(DateTimeZone.forID("UTC"));
When you are creating first date, you are fixing the zone, with the second you don't. So either remove the zone, or set the same in both places.
You could also convert both DateTime to LocalDate, it also works for this example, but first solution should be a better case.

Time difference - strange result

I have very simple code which calculates difference between two times:
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
public class JavaApplication8 {
private static final SimpleDateFormat timeFormat = new SimpleDateFormat("hh:mm:ss.SSS");
public static void main(String[] args) throws InterruptedException {
Date start = GregorianCalendar.getInstance().getTime();
Thread.sleep(100);
Date end = GregorianCalendar.getInstance().getTime();
long diff = end.getTime() - start.getTime();
System.out.println(timeFormat.format(diff));
}
}
but it prints 01:00:00.100 instead of 00:00:00.100, why?
Other way to solve this. Actually time diff that you having is not millisecs of current time. Its is just time diff, so make a simple division of that u can have hours:mins:secs.
And its quite fast.
Date start = GregorianCalendar.getInstance().getTime();
Thread.sleep(100);
Date end = GregorianCalendar.getInstance().getTime();
long longVal = end.getTime() - start.getTime();
long hours = longVal / 3600000;
long mins = (longVal % 3600) / 60000;
long secs = longVal % 60000;
System.out.println(hours + " " + mins + " " + secs);
You have mixed up two concepts:
You are measuring a time interval (difference between TWO points in time)
You are printing a date (ONE single point in time)
The two are not compatible, you will always get such strange effects. In your case, as pointed out on the other comments, the time zone gets mixed in. The concept of time zones exists only for dates (point in time), but makes no sense for intervals.
You can use the Jodatime library or the JSR 310: Date and Time API (coming with Java 8 I think).
With Jodatime you can explicitely construct a interval:
DateTime start = new DateTime(2004, 12, 25, 0, 0, 0, 0);
DateTime end = new DateTime(2005, 1, 1, 0, 0, 0, 0);
Period period = new Period(start, end);
and then format it with a PeriodFormatter
PeriodFormatter daysHoursMinutes = new PeriodFormatterBuilder()
.appendDays()
.appendSuffix(" day", " days")
.appendSeparator(" and ")
.appendMinutes()
.appendSuffix(" minute", " minutes")
.appendSeparator(" and ")
.appendSeconds()
.appendSuffix(" second", " seconds")
.toFormatter();
System.out.println(daysHoursMinutes.print(period));
By separating the concepts of ONE point in time and the time between TWO points in time, you can make sure that there aren't any other surprises (e.g. leap seconds).
It's a timezone issue. DateFormat.format() will by default format the date in your default time zone, which seem to be UTC+1.
You should set the timezone for timeFormat to UTC:
timeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(timeFormat.format(diff));
Also, you should use HH instead of hh in your DateFormat. hh is for 12-hour clock.
new SimpleDateFormat("HH:mm:ss.SSS");
Update :
But there is some other major issue. Currently you are trying to format a duration, which you should not do. Java Date API, do not have any concept of period or duration.
The value which you get from formatting is nothing but the number of milliseconds (equivalent to the difference) from epoch. It's returning a Date object, instead. Although the result might seem correct, but technically, the difference between two dates denotes a period or duration, which is not the same as Date (which denotes a particular instant of time).
You should consider moving to Joda Time for this task, which has classes representing these concepts like Period, Instant, and Duration.
Because your time zone is GMT+1.
If you read the documentation, you'll find what getTime() does:
Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
represented by this Date object.
So 100 ms means January 1, 1970, 00:00:00.100 GMT, which is January 1, 1970, 01:00:00.100 GMT+1.
You can simply set the time zone you want your time converted to:
timeFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
And you want 24h-style format: HH:mm:ss.SSS, otherwise it will show 12 instead of 00 hours.
EDIT: as jarnbjo said: you're trying to apply a date formatter to an interval of time, which obviously won't work as you expect. There's no such time interval formatters in the Java API. You'll have to write your own.

Using Joda-Time to get UTC offset for a given date and timezone

I have dates in the format 20Jan2013, 08Aug2012 etc, with their own specific timezones. So for example, 20Jan2013 might have a timezone ID of Australia/Melbourne, and 08Aug2012 might have an ID of Europe/London. What I want to do is, based on these timezones and the dates, calculate the UTC offset for that timezone on the given date. I've come up with this so far:
DateTimeFormatter dtf = DateTimeFormat.forPattern("ZZ");
DateTimeFormatter dtf1 = DateTimeFormat.forPattern("ddMMMYYYY");
DateTimeZone zone = DateTimeZone.forID("Australia/Melbourne");
DateTime thisDate = dtf1.parseDateTime("30Jul2013");
System.out.println("\nZone: " + thisDate.withZone(zone));
This gives me the output:
Zone: 2013-07-30T00:00:00.000+10:00
This is correct, but I would like to extract just the UTC offset from this, which in this case is +10:00. I've looked for ways to do this but can't find anything. Is there any way I can do this? The only option I see is to convert the output to a String and use the substring method to get the UTC offset.
The above code does take DST (Daylight Saving Time) into account. So for example if I had:
DateTime thisDate = dtf1.parseDateTime("30Jan2013");
The output would be: 2013-01-30T00:00:00.000+11:00
(+11:00 at the end instead of +10:00)
So basically all I need to do is find a way to extract +11:00 from 2013-07-30T00:00:00.000+11:00. Please help!
Simple Method for Obtaining Timezone Name and Offset in Hours
public static String getCurrentTimeZoneOffset() {
DateTimeZone tz = DateTimeZone.getDefault();
Long instant = DateTime.now().getMillis();
String name = tz.getName(instant);
long offsetInMilliseconds = tz.getOffset(instant);
long hours = TimeUnit.MILLISECONDS.toHours( offsetInMilliseconds );
String offset = Long.toString( hours );
return name + " (" + offset + " Hours)";
// Example: "Mountain Standard Time (-7 Hours)"
}
Couple caveats:
This gets the default DateTimeZone from JodaTime. You can modify it to accept a specific DateTimeZone that is passed into the method.
This returns it in a format like "Mountain Standard Time (-7 Hours)" but you can format it as you see fit quite easily.
Hope that helps.
JP
In order for Joda to give the correct offset, you must provide a datetime instant.Without a datetime instant, it is impossible to calculate the offset since we have different offsets(daylight savings). This is how I would use Joda to get offset in + HH:mm format :
int offsetInMillis = DateTimeZone.forID(zoneId).getOffset(new DateTime().getMillis());
String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000),
Math.abs((offsetInMillis / 60000) % 60));
offset = (offsetInMillis >= 0 ? "+" : "-") + offset;
If you just need the timezone offset, use DateTimeZone.forID() to get the time zone and then tz.getOffset(instant) to get the offset to UTC in milliseconds.
It may look odd that you need an instant to calculate the offset to UTC but this is necessary to take Daylight Savings into account as well as changes in the timezone. Yes, countries change their timezones once in a while:
Why does timezone data change?
Timezone settings are adopted locally, and there is no world timezone authority.
EDIT This gives you the correct result:
DateTimeFormatter dtf1 = DateTimeFormat.forPattern("ddMMMYYYY");
DateTimeZone zone = DateTimeZone.forID("Australia/Melbourne");
DateTime thisDate = dtf1.parseDateTime("30Jul2013").withZone(zone);
assertEquals( 10 * CommonConstants.MILLISECONDS_PER_HOUR,
zone.getOffset( thisDate ) );
thisDate.get
Java 8 introduced better Date and Time handling to address some of the language's previous limitations in that area. A few of my projects have started to use it rather than Joda.
Using the java.time package:
ZonedDateTime dateTime = LocalDate.of(2013 , 1 , 20).atStartOfDay( ZoneId.of("Australia/Melbourne"));
ZoneOffset zo = dateTime.getOffset();
int offset = zo.getTotalSeconds();
long hours = TimeUnit.SECONDS.toHours(offset);
long minutes = TimeUnit.SECONDS.toMinutes(offset % 3600);
The hours variable is set to 11 and the minutes to 0.
It also calculates the minutes-offset, for time zones that are partial hours, such as Newfoundland and Labrador in eastern Canada:
ZonedDateTime dateTime = LocalDate.of(2013, 1, 20).atStartOfDay( ZoneId.of("Canada/Newfoundland"));
In this case, the offset is -03:30 (three and a half hours behind UTC), hours is -3 and minutes is -30.
For the String representation, rather than the integer number of hours and minutes, use the ZoneOffset's toString() method. So for the example above, use:
String offsetString = zo.toString();
When you know offset and timestamp so in order to get current time you can use
public static String formatMonthDayMinuteByGivenUtcOffset(long timestamp, int offset) {
return JODA_FORMATTER.print(createDateTime(timestamp, offset));
}

Confused about date and time in Excel

I have Java time (ms since 1/1/1970 UTC) and would like to write that time to a csv file, so that Excel can correctly interpret and format it. I understand, that excel uses "serial date time" as a format - that is a floating point number, where the integer part gives the number of days since 1/1/1900 and the decimal part gives fractions of a day.
I fail to understand timezone and daylight saving time handling in this.
This page says that the excel epoch (1/1/1900) is based on the local (=computer creating the Excel file?) timezone. This means that a serial date does not indicate a unique instant in time without the info which computer timezone created it. Not what I would have chosen, but OK.
Now accepting this, I believed I could convert Java time to Excel serial date by the following Java code (nb: I'm in Zurich, CET timezone):
private static final long ONE_HOUR= 60L * 60 * 1000;
private static final long ONE_DAY = 24 * ONE_HOUR;
private static final long excelEpoch;
static{
Calendar cal;
cal = Calendar.getInstance(TimeZone.getTimeZone("Europe/Zurich"));
cal.set(Calendar.YEAR, 1900);
cal.set(Calendar.DAY_OF_YEAR, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
excelEpoch = cal.getTimeInMillis();
}
private static String formatForExcel(long time){
return ""+(time-excelEpoch)/(double)ONE_DAY;
}
Using this I can print out a few times:
public static void main(String[] args) {
String sep = "\t"; // csv field separator
SimpleDateFormat fmt = new SimpleDateFormat("HH:mm:ss d/M/yyyy");
fmt.setTimeZone(TimeZone.getTimeZone("Europe/Zurich"));
System.out.println("Time in ms since 1/1/1970 UTC"+ sep + "Time as string" + sep + "Excel serial" + sep + "Excel serial formatted by excel");
long startTime = 1332630000000L; // 25/3/2012 00:00 CET , shortly before change from winter time to DST
for (long t = startTime; t < startTime + 4*ONE_HOUR; t+=ONE_HOUR) {
System.out.println(t + sep + fmt.format(new Date(t)) + sep + formatForExcel(t) + sep + formatForExcel(t));
}
}
Which returns
Time in ms since 1/1/1970 UTC Time as string Excel serial Excel serial formatted by excel
1332630000000 00:00:00 25/3/2012 40991.0 40991.0
1332633600000 01:00:00 25/3/2012 40991.041666666664 40991.041666666664
1332637200000 03:00:00 25/3/2012 40991.083333333336 40991.083333333336
1332640800000 04:00:00 25/3/2012 40991.125 40991.125
Note that the change from winter time to DST happens in those hours (check second column, hour 2 is missing).
Now comes the confusion. If I paste this in excel, and for the last column choose "Format cells..." and then "Time" (any of the formats), it prints:
Time in ms since 1/1/1970 UTC Time as string Excel serial Excel serial formatted by excel
1332630000000 25.03.2012 00:00 40991 0:00:00
1332633600000 25.03.2012 01:00 40991.04167 1:00:00
1332637200000 25.03.2012 03:00 40991.08333 2:00:00
1332640800000 25.03.2012 04:00 40991.125 3:00:00
Note, that excel in formatting the serial date, does not change to DST. So this is not wallclock time.
Long story short:
How should I convert Java time to Excel so that it just works?
I suspect that Excel doesn't really take the time zone into account. I suspect it's really just treating it as a "local time" where every conceivable date/time is valid. (A "local instant" in Joda Time parlance, I believe - although I don't know how widely that's used.)
I suspect there's no way of representing a specific instant in time, and that instead you should:
Take whatever date/time you want to represent as a local time (e.g. "25th March 2012, 3am")
Put that into a Calendar which is set to use UTC
Take the millis from calendar.getTime().getTime()
Subtract the "Excel epoch" value of 1900-01-01T00:00:00Z (again, obtain via a calendar which is set to UTC)
Divide by "millis per day"
Now there's also an oddity with Excel in terms of its handling of dates before March 1st 1900, but hopefully that won't bite you.
Convert floating point "serial date/time" to "mills since 1970/1/1"
Note: daysFrom1900to1970 works for google spreadsheet dates, but might need slight adjustment for excel
int daysFrom1900to1970 =365*70 + 19; // Or maybe =365*70 + 17 But 19 worked.
int millisPerDay = 1000 * 60 * 60 * 24;
long millisSince1970 = (long) ((timeToSend.doubleValue() - daysFrom1900to1970) * millisPerDay );
Calendar dateTimeToSend = Calendar.getInstance();
dateTimeToSend.setTimeZone(TimeZone.getTimeZone("GMT"));
dateTimeToSend.setTimeInMillis(millisSince1970);
System.out.println("timeToSend:"+ new SimpleDateFormat("yyyy.MM.dd HH:mm:ss z").format(dateTimeToSend.getTime()));

Get timzone compared to GMT in Android

I need to get the mobile TimeZone comparing to GMT in Android. I only could see one function returns that but as String:
Calendar c = Calendar.getInstance();
TimeZone tz = c.getTimeZone();
tz.getID();
This is the description of getID():
Returns the ID of this TimeZone, such as America/Los_Angeles, GMT-08:00 or UTC.
The problem is I need to get that as Integer like +3, -5...
You should be able to calculate the difference based on the TimeZone getOffset() value, see http://developer.android.com/reference/java/util/TimeZone.html#getOffset(long)
public static String getCurrentTimezoneOffset() {
TimeZone tz = TimeZone.getDefault();
Calendar cal = GregorianCalendar.getInstance(tz);
int offsetInMillis = tz.getOffset(cal.getTimeInMillis());
String offset = String.format("%02d:%02d", Math.abs(offsetInMillis / 3600000), Math.abs((offsetInMillis / 60000) % 60));
offset = (offsetInMillis >= 0 ? "+" : "-") + offset;
return offset;
}
Use TimeZone.getOffset. Be aware that the time difference can change due to daylight saving time and that can widely vary per country and day of year. You should therefore not rely on that offset number throughout the year. Instead it is more reliable to use the TimeZone identifier instead.

Categories

Resources