Часовой пояс в Android
У меня есть время в миллисекундах, и я показываю это время в своем приложении в формате "MM/dd/yyyy HH:mm:ss"
, он работает нормально.
Проблема: если я изменяю часовой пояс в устройстве Android, это отображает разное время в моей заявке, возможно, из-за некоторого вычисления часового пояса. Я хочу отображать то же время, что и в моей базе данных, как и в любой временной зоне.
Я использую ниже код для проверки проблемы с часовым поясом
Locale locale = new Locale("en", "IN");
TimeZone tz = TimeZone.getDefault();
System.out.println("Default timezon id :: " + tz.getID());
tz.setID("Asia/Calcutta");
String timezon = tz.getDisplayName(false, TimeZone.SHORT, locale);
System.out.println("Timezon id :: " + tz.getID() + " Timezon name :: " + timezon);
Calendar cal = Calendar.getInstance(tz, locale);
System.out.println("TImezon :: " + tz);
// "1319084400775" is the milliseconds of 10/20/2011 05:20:00 in MM/dd/yyyy HH:mm:ss format
Date date = new Date(Long.parseLong("1319084400775"));
System.out.println("Date :: " + date.toGMTString());
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale);
System.out.println("Start date :: " + format.format(date));
// "1319084400775" is the milliseconds of 10/20/2011 05:20:00 in MM/dd/yyyy HH:mm:ss format
cal.setTimeInMillis(Long.parseLong("1319084400775"));
timezon = cal.getTimeZone().getDisplayName(false, TimeZone.SHORT, locale);
System.out.println("Calender timezon :: " + timezon);
System.out.println("Start date :: yyyy-mm-dd hh:mm:ss " + cal.get(Calendar.YEAR) + "-" + cal.get(Calendar.MONTH) + "-" + cal.get(Calendar.DAY_OF_MONTH) + " " + cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE));
// "1319084700776" is the milliseconds of 10/20/2011 05:25:00 in MM/dd/yyyy HH:mm:ss format
cal.setTimeInMillis(Long.parseLong("1319084700776"));
System.out.println("End date :: " + cal.getTime());
Выход::
Если я установил часовой пояс для "Pacific/Fiji",
10-07 17:03:40.392: INFO/System.out(1193): Default timezon id :: Pacific/Fiji
10-07 17:03:40.392: INFO/System.out(1193): Timezon id :: Asia/Calcutta Timezon name :: GMT+05:30
10-07 17:03:40.406: INFO/System.out(1193): TImezon :: [email protected]
10-07 17:03:40.422: INFO/System.out(1193): Date :: 20 Oct 2011 04:20:00 GMT
10-07 17:03:40.442: INFO/System.out(1193): Start date :: 2011-10-20 16:20:00
10-07 17:03:40.442: INFO/System.out(1193): Calender timezon :: GMT+05:30
10-07 17:03:40.442: INFO/System.out(1193): Start date :: yyyy-mm-dd hh:mm:ss 2011-9-20 16:20
10-07 17:03:40.452: INFO/System.out(1193): End date :: Thu Oct 20 16:25:00 Pacific/Fiji 2011
Если я установил часовой пояс для "Америка/Тихуана";
10-06 22:05:20.702: INFO/System.out(1193): Default timezon id :: America/Tijuana
10-06 22:05:20.712: INFO/System.out(1193): Timezon id :: Asia/Calcutta Timezon name :: GMT+05:30
10-06 22:05:20.712: INFO/System.out(1193): TImezon :: [email protected]4e658
10-06 22:05:20.733: INFO/System.out(1193): Date :: 20 Oct 2011 04:20:00 GMT
10-06 22:05:20.742: INFO/System.out(1193): Start date :: 2011-10-19 21:20:00
10-06 22:05:20.742: INFO/System.out(1193): Calender timezon :: GMT+05:30
10-06 22:05:20.752: INFO/System.out(1193): Start date :: yyyy-mm-dd hh:mm:ss 2011-9-19 21:20
10-06 22:05:20.752: INFO/System.out(1193): End date :: Wed Oct 19 21:25:00 America/Tijuana 2011
ИЗМЕНИТЬ
У меня есть время в миллисекундах теперь я показываю, что миллисекунды в формате даты в моем приложении, но проблема заключается в том, что я изменил часовой пояс в устройстве, которое я получаю в соответствии с этим часовым поясом.
Ответы
Ответ 1
Дата - это всего лишь мгновение в универсальное время. Он не имеет понятия о часовом поясе. Подумайте об этом как "когда Кеннеди был убит".
Когда вы показываете это время с помощью SimpleDateFormat
, этот формат даты имеет часовой пояс, и вы показываете этот момент времени с помощью этого часового пояса. Таким образом, если часовой пояс формата даты является центральным стандартным временем, это время будет отображаться как 12:30. Если часовой пояс UTC, он будет отображаться как 18:30.
Если вы хотите, чтобы какая-либо дата отображалась одинаково, независимо от часового пояса, вам просто нужно выбрать определенный часовой пояс (например, UTC) и всегда показывать дату с этим часовым поясом. Таким образом, вы должны вызвать setTimeZone
в DateFormat
перед форматированием даты.
Ответ 2
В стандартной версии Java:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
sdf.setTimeZone(TimeZone.getTimeZone(<your timezone here>);
long millis = <your timestamp here>; //timestamps are not TZ dependent.
Date d = new Date(millis);
String toDisplay = sdf.format(d);
Часовой пояс в SimpleDateFormat
- это фиксированный часовой пояс, который вы хотите использовать для каждой отображаемой даты, а не по умолчанию для устройства.
Также убедитесь, что столбец временной метки в вашей базе данных начинает отсчет в тот же момент времени, что и Java (1/1/1970, эпоха AKA Unix), и имеет ту же самую прецессию (миллисекунды).
Существует еще один класс android.text.format.DateFormat, но я не вижу смысла использовать его.
Ответ 3
Я получаю решение, подобное методу ниже
/**
* Date time must be in milliseconds
* return Time in milliseconds
*/
public static String getTimeInMilli(Context ctx, String datetime) {
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(Long.parseLong(datetime));
//This will return daylight savings offset in milliseconds.You have to Subtract this milliseconds from calendar
int dayLightSaving = cal.get(Calendar.DST_OFFSET);
cal.setTimeInMillis(cal.getTimeInMillis() - dayLightSaving);
TimeZone z = cal.getTimeZone();
int offset = z.getRawOffset();
int offsetHrs = offset / 1000 / 60 / 60;
int offsetMins = offset / 1000 / 60 % 60;
// Subtract offset of your current TimeZone
cal.add(Calendar.HOUR_OF_DAY, (-offsetHrs));
cal.add(Calendar.MINUTE, (-offsetMins));
cal.setTimeZone(TimeZone.getTimeZone("GMT"));
//add offset of your TimeZone
cal.add(Calendar.HOUR_OF_DAY, 5);
cal.add(Calendar.MINUTE, 30);
return String.valueOf(cal.getTimeInMillis());
}
Теперь, если я изменю часовой пояс на своем устройстве, моя дата приложения останется прежней.