Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android DateUtils.formatDateTime wrong timezone

String time = DateUtils.formatDateTime(context, 1469602800000, DateUtils.FORMAT_SHOW_TIME);

The result is: 03:00 as expected

My current timezone is: GMT+3:00 DST

But how can I get: "00:00" if I can't pass the timezone to the dateformatter?

I have already tried:

TimeZone timeZone = getTimezoneForId("America/Los_Angeles");

Calendar calendar = Calendar.getInstance();
calendar.setTimeZone(timeZone);
calendar.setTimeInMillis(1469602800000);

String time = new SimpleDateFormat("HH:mm", Locale.getDefault()).format(calendar.getTime());

But I'm getting the same result: "03:00"

like image 455
Zbarcea Christian Avatar asked Jul 26 '16 16:07

Zbarcea Christian


2 Answers

I got the solution for DateUtils without using such a heavy object as Calendar or even SimpleDateFormat.

// Your UTC time in milliseconds:
long timeInMillis = 1469602800000;

// Desired timezone ID:
String timezoneId = "UTC";

java.util.Formatter f = new java.util.Formatter(new StringBuilder(50), Locale.getDefault());
String time = DateUtils.formatDateRange(context, f, timeInMillis, timeInMillis, DateUtils.FORMAT_SHOW_TIME, timezoneId).toString();

EXPLANATION:

If you look at the source code, you will find that when you call

formatDateTime(Context context, long millis, int flags)

it returns the result of the call

formatDateRange(context, millis, millis, flags);

which is implemented as follows:

public static String formatDateRange(Context context, long startMillis,long endMillis, int flags) {
Formatter f = new Formatter(new StringBuilder(50), Locale.getDefault());
return formatDateRange(context, f, startMillis, endMillis, flags).toString();
}

Again, looking at the source code for

formatDateRange(context, f, startMillis, endMillis, flags)

you will see the following:

return formatDateRange(context, formatter, startMillis, endMillis, flags, null);

If you look closely at the last line, you will see that it provides null as the String timezone parameter. Hence, according to the annotation of the method, it will compute the value for your local timezone. Official docs suggest to use Time.TIMEZONE_UTC, but that thing is deprecated, so in my solution I set the timezone explicitly (timezoneId = "UTC"). You can set any timezone you need, e.g. "Pacific/Honolulu" or even "Asia/Novosibirsk". Here is a link for a complete list of timezones IDs.

PLEASE NOTE

  1. If you want your time String to be formatted in a specific locale, initialize the Formatter providing that specific locale as an initialization argument.
  2. The benefit of the provided solution is that the time String will be correctly formatted according to the default locale of the device. But if you want to use a specific format for your time representation, that will also be consistent on all devices, use SimpleDateFormat.
like image 188
Sevastyan Savanyuk Avatar answered Nov 20 '22 16:11

Sevastyan Savanyuk


I got the problem.

You are setting the TimeZone for calendar object. Howewever, you must set TimeZone to your SimpleDateFormat as well. Otherwise, SimpleDateFormat will receive calendar.getTime() but will handle it in your default TimeZone.

So, code below will work:

Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("America/Los_Angeles"));
calendar.setTimeInMillis(1469602800000L);

SimpleDateFormat dateFormated = new SimpleDateFormat("HH:mm");
dateFormated.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));


String time = dateFormated.format(calendar.getTime());

I tested and works fine.

OR

You can just do:

SimpleDateFormat dateFormated = new SimpleDateFormat("HH:mm");
dateFormated.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
String time = dateFormated.format(1469602800000L);
like image 41
W0rmH0le Avatar answered Nov 20 '22 15:11

W0rmH0le