Как преобразовать метку времени UTC в местное время устройства в android

Мне нужно преобразовать отметку времени UTC, которую я получаю с сервера на локальное время устройства. в настоящее время я получаю 5 часов разницы во времени. например, когда я отправляю на сервер пост раз 5 часов назад, а не секунду назад. Как исправить эту проблему. спасибо

Ниже приведен код, который я делаю

long timestamp = cursor.getLong(columnIndex);
            CharSequence relTime = DateUtils
                    .getRelativeTimeSpanString(timestamp * 1000
                            + TimeZone.getDefault().getRawOffset(),
                            System.currentTimeMillis(),
                            DateUtils.MINUTE_IN_MILLIS);
            ((TextView) view).setText(relTime);

7 ответов


код в вашем примере выглядит отлично на первый взгляд. Кстати, если метка времени сервера находится в UTC (т. е. это метка времени эпохи), вам не нужно применять текущее смещение часового пояса. Другими словами, если метка времени сервера находится в UTC, вы можете просто получить разницу между меткой времени сервера и системным временем (System.currentTimeMillis()), поскольку системное время находится в UTC (epoch).

Я бы проверил, что метка времени, поступающая с вашего сервера, - это то, что вы ожидаете. Если время от сервер не преобразуется в ожидаемую дату (в локальном часовом поясе), тогда разница между меткой времени и текущим системным временем не будет такой, как вы ожидаете.

использовать Calendar получить текущий часовой пояс. Инициализировать SimpleDateFormatter с текущим часовым поясом; затем войдите в метку времени сервера и убедитесь, что это дата, которую вы ожидаете:

Calendar cal = Calendar.getInstance();
TimeZone tz = cal.getTimeZone();

/* debug: is it local time? */
Log.d("Time zone: ", tz.getDisplayName());

/* date formatter in local timezone */
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
sdf.setTimeZone(tz);

/* print your timestamp and double check it's the date you expect */
long timestamp = cursor.getLong(columnIndex);
String localTime = sdf.format(new Date(timestamp * 1000)); // I assume your timestamp is in seconds and you're converting to milliseconds?
Log.d("Time: ", localTime);

если серверное время, которое печатается не что вы ожидаете, то ваше время сервера не в UTC.

если серверное время, которое печатается дата, которую вы ожидаете, то вы не должны применять rawoffset к нему. Таким образом, ваш код будет проще (минус все ведение журнала отладки):

long timestamp = cursor.getLong(columnIndex);
Log.d("Server time: ", timestamp);

/* log the device timezone */
Calendar cal = Calendar.getInstance();
TimeZone tz = cal.getTimeZone();
Log.d("Time zone: ", tz.getDisplayName());

/* log the system time */
Log.d("System time: ", System.currentTimeMillis());

CharSequence relTime = DateUtils.getRelativeTimeSpanString(
    timestamp * 1000,
    System.currentTimeMillis(),
    DateUtils.MINUTE_IN_MILLIS);

((TextView) view).setText(relTime);

int offset = TimeZone.getDefault().getRawOffset() + TimeZone.getDefault().getDSTSavings();
long now = System.currentTimeMillis() + offset;

преобразование строки даты формата "2011-06-23T15:11: 32" в наш часовой пояс.

private String getDate(String ourDate)
{
    try
    {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date value = formatter.parse(ourDate);

        SimpleDateFormat dateFormatter = new SimpleDateFormat("MM-dd-yyyy HH:mm"); //this format changeable
        dateFormatter.setTimeZone(TimeZone.getDefault());
        ourDate = dateFormatter.format(value);

        //Log.d("ourDate", ourDate);
    }
    catch (Exception e)
    {
        ourDate = "00-00-0000 00:00";
    }
  return ourDate;
}

Я сделал что-то вроде этого, чтобы получить дату в часовом поясе локального устройства от отметки времени UTC.

private long UTC_TIMEZONE=1470960000;
private String OUTPUT_DATE_FORMATE="dd-MM-yyyy - hh:mm a"

getDateFromUTCTimestamp(UTC_TIMEZONE,OUTPUT_DATE_FORMATE);

здесь функция

 public String getDateFromUTCTimestamp(long mTimestamp, String mDateFormate) {
        String date = null;
        try {
            Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
            cal.setTimeInMillis(mTimestamp * 1000L);
            date = DateFormat.format(mDateFormate, cal.getTimeInMillis()).toString();

            SimpleDateFormat formatter = new SimpleDateFormat(mDateFormate);
            formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
            Date value = formatter.parse(date);

            SimpleDateFormat dateFormatter = new SimpleDateFormat(mDateFormate);
            dateFormatter.setTimeZone(TimeZone.getDefault());
            date = dateFormatter.format(value);
            return date;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return date;
    }

результат :

12-08-2016 - 04:30 PM 

надеюсь, это сработает для других.


локальный в UTC

DateTime dateTimeNew = new DateTime(date.getTime(),
DateTimeZone.forID("Asia/Calcutta"));
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
String datetimeString = dateTimeNew.toString("yyyy-MM-dd HH:mm:ss");
long milis = 0;
try {
     milis = simpleDateFormat.parse(datetimeString).getTime();
} catch (ParseException e) {
   e.printStackTrace();
}

Это может помочь кому-то с тем же требованием

private String getDate(long time){
        SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy hh:mm a");
        String dateString = formatter.format(new Date(time));
        String date = ""+dateString;
        return date;
    }

Я сделал это с помощью Extension Functions на kotlin

fun String.toDate(dateFormat: String = "yyyy-MM-dd HH:mm:ss", timeZone: TimeZone = TimeZone.getTimeZone("UTC")): Date {
    val parser = SimpleDateFormat(dateFormat, Locale.getDefault())
    parser.timeZone = timeZone
    return parser.parse(this)
}

fun Date.formatTo(dateFormat: String, timeZone: TimeZone = TimeZone.getDefault()): String {
    val formatter = SimpleDateFormat(dateFormat, Locale.getDefault())
    formatter.timeZone = timeZone
    return formatter.format(this)
}

использование:

"2018-09-10 22:01:00".toDate().formatTo("dd MMM yyyy")

Output: "11 Sep 2018"

Примечание:

обеспечить надлежащую проверку.