49

サーバーから取得したUTCタイムスタンプをローカルデバイスの時刻に変換する必要があります。現在、時間に5時間の差があります。たとえば、サーバーに投稿する場合、投稿時間は1秒前ではなく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);
4

11 に答える 11

69

Java:

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

Kotlin:

val offset: Int = TimeZone.getDefault().rawOffset + TimeZone.getDefault().dstSavings
val now: Long = System.currentTimeMillis() - offset
于 2013-03-27T18:31:07.080 に答える
52

「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;
}
于 2015-09-09T12:57:48.587 に答える
45

あなたの例のコードは一見うまく見えます。ところで、サーバーのタイムスタンプがUTCである場合(つまり、エポックタイムスタンプである場合)、現在のタイムゾーンオフセットを適用する必要はありません。System.currentTimeMillis()つまり、サーバーのタイムスタンプがUTCである場合、システム時刻はUTC(エポック)であるため、サーバーのタイムスタンプとシステム時刻()の差を簡単に取得できます。

サーバーからのタイムスタンプが期待どおりであることを確認します。サーバーからのタイムスタンプが(ローカルタイムゾーンで)期待する日付に変換されない場合、タイムスタンプと現在のシステム時刻の差は期待どおりにはなりません。

Calendar現在のタイムゾーンを取得するために使用します。SimpleDateFormatter現在のタイムゾーンでaを初期化します。次に、サーバーのタイムスタンプをログに記録し、それが予期した日付であるかどうかを確認します。

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);
于 2013-02-13T13:12:21.760 に答える
9

で使ってみ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"

ノート:

適切な検証を確認してください。

于 2018-09-11T18:31:16.850 に答える
2

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 

これが他の人のために働くことを願っています。

于 2016-08-10T09:45:30.550 に答える
1

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();
}
于 2014-11-28T13:22:46.800 に答える
1

@prgDevelopからの回答は、AndroidMarsmallowで0を返します。7200000を返す必要があります。これらの変更により、正常に機能します。

int offset = TimeZone.getTimeZone(Time.getCurrentTimezone()).getRawOffset() + TimeZone.getTimeZone(Time.getCurrentTimezone()).getDSTSavings();
于 2019-08-26T06:19:43.897 に答える
1

java.time

java.utilDate-Time APIとそのフォーマットAPIはSimpleDateFormat古く、エラーが発生しやすいです。それらの使用を完全に停止し、最新の日時API *に切り替えることをお勧めします。

java.time最新の日時APIを使用したソリューション:

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

public class Main {
    public static void main(String[] args) {
        // A sample timestamp as Unix epoch (i.e. seconds from 01-01-1970T00:00:00 GMT)
        long epochSeconds = 1632131465L;

        // Note: Use Instant#ofEpochMilli in case you have timestamp in milliseconds
        Instant instant = Instant.ofEpochSecond(epochSeconds);
        System.out.println(instant);

        LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        System.out.println(ldt);
    }
}

私のタイムゾーン、ヨーロッパ/ロンドンでの出力:

2021-09-20T09:51:05Z
2021-09-20T10:51:05

ONLINE DEMO

はタイムライン上の瞬間的なInstantポイントを表し、通常はUTC時間で表されます。Z出力のは、ゼロタイムゾーンオフセットのタイムゾーン指定子です。Zuluの略で、Etc/UTCタイムゾーンを指定します(タイムゾーンオフセットは+00:00時間です)。

Trail: DateTimeから最新のDate-TimeAPIの詳細をご覧ください。


*何らかの理由で、Java6またはJava7に固執する必要がある場合は、 Java.time機能のほとんどをJava6および7にバックポートするThreeTen-Backportを使用できます。AndroidプロジェクトおよびAndroidAPIで作業している場合レベルはまだJava-8に準拠していません。脱糖によって利用可能なJava8+APIAndroidプロジェクトでのThreeTenABPの使用方法を確認してください。

于 2021-09-20T10:00:10.827 に答える
0

これは、同じ要件を持つ人に役立つ可能性があります

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;
    }
于 2017-02-05T06:08:25.350 に答える
0

私も同様の問題を抱えていました。UTCタイムスタンプをタイムゾーンカレンダーに設定し、日付をフォーマットするだけです。タイムスタンプは、タイムゾーンに関係なく同じです。

val local = Calendar.getInstance()   // get your device timezone calendar
local.timeInMillis = <timestamp>

val sdf = SimpleDateFormat("dd/MM/yyyy HH:mm:ss")
val formatted = sdf.format(Date(local.timeInMillis))
于 2021-04-27T21:24:34.740 に答える
-1

それは働いています

使用する場所でこのメソッドを呼び出します

SntpClient client = new SntpClient();
if (client.requestTime("ntp.ubuntu.com", 30000)) {
  long now = client.getNtpTime();
  Date current = new Date(now);

  date2 = sdf.parse(new Date(current.getTime()).toString());
 // System.out.println(current.toString());
  Log.e(TAG, "testing SntpClient time current.toString() "+current.toString()+" , date2 = "+date2);
}

=====================================================   

import android.os.SystemClock;
import android.util.Log;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * {@hide}
 *
 * Simple SNTP client class for retrieving network time.
 *
 * Sample usage:
 * <pre>SntpClient client = new SntpClient();
 * if (client.requestTime("time.foo.com")) {
 *     long now = client.getNtpTime() + SystemClock.elapsedRealtime() - client.getNtpTimeReference();
 * }
 * </pre>
 */
public class SntpClient
{
  private static final String TAG = "SntpClient";

  private static final int REFERENCE_TIME_OFFSET = 16;
  private static final int ORIGINATE_TIME_OFFSET = 24;
  private static final int RECEIVE_TIME_OFFSET = 32;
  private static final int TRANSMIT_TIME_OFFSET = 40;
  private static final int NTP_PACKET_SIZE = 48;

  private static final int NTP_PORT = 123;
  private static final int NTP_MODE_CLIENT = 3;
  private static final int NTP_VERSION = 3;

  // Number of seconds between Jan 1, 1900 and Jan 1, 1970
  // 70 years plus 17 leap days
  private static final long OFFSET_1900_TO_1970 = ((365L * 70L) + 17L) * 24L * 60L * 60L;

  // system time computed from NTP server response
  private long mNtpTime;

  // value of SystemClock.elapsedRealtime() corresponding to mNtpTime
  private long mNtpTimeReference;

  // round trip time in milliseconds
  private long mRoundTripTime;

  /**
   * Sends an SNTP request to the given host and processes the response.
   *
   * @param host host name of the server.
   * @param timeout network timeout in milliseconds.
   * @return true if the transaction was successful.
   */
  public boolean requestTime(String host, int timeout) {
    DatagramSocket socket = null;
    try {
      socket = new DatagramSocket();
      socket.setSoTimeout(timeout);
      InetAddress address = InetAddress.getByName(host);
      byte[] buffer = new byte[NTP_PACKET_SIZE];
      DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_PORT);

      // set mode = 3 (client) and version = 3
      // mode is in low 3 bits of first byte
      // version is in bits 3-5 of first byte
      buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);

      // get current time and write it to the request packet
      long requestTime = System.currentTimeMillis();
      long requestTicks = SystemClock.elapsedRealtime();
      writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime);

      socket.send(request);

      // read the response
      DatagramPacket response = new DatagramPacket(buffer, buffer.length);
      socket.receive(response);
      long responseTicks = SystemClock.elapsedRealtime();
      long responseTime = requestTime + (responseTicks - requestTicks);

      // extract the results
      long originateTime = readTimeStamp(buffer, ORIGINATE_TIME_OFFSET);
      long receiveTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);
      long transmitTime = readTimeStamp(buffer, TRANSMIT_TIME_OFFSET);
      long roundTripTime = responseTicks - requestTicks - (transmitTime - receiveTime);
      // receiveTime = originateTime + transit + skew
      // responseTime = transmitTime + transit - skew
      // clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2
      //             = ((originateTime + transit + skew - originateTime) +
      //                (transmitTime - (transmitTime + transit - skew)))/2
      //             = ((transit + skew) + (transmitTime - transmitTime - transit + skew))/2
      //             = (transit + skew - transit + skew)/2
      //             = (2 * skew)/2 = skew
      long clockOffset = ((receiveTime - originateTime) + (transmitTime - responseTime))/2;
      // if (false) Log.d(TAG, "round trip: " + roundTripTime + " ms");
      // if (false) Log.d(TAG, "clock offset: " + clockOffset + " ms");

      // save our results - use the times on this side of the network latency
      // (response rather than request time)
      mNtpTime = responseTime + clockOffset;
      mNtpTimeReference = responseTicks;
      mRoundTripTime = roundTripTime;
    } catch (Exception e) {
      if (false) Log.d(TAG, "request time failed: " + e);
      return false;
    } finally {
      if (socket != null) {
        socket.close();
      }
    }

    return true;
  }

  /**
   * Returns the time computed from the NTP transaction.
   *
   * @return time value computed from NTP server response.
   */
  public long getNtpTime() {
    return mNtpTime;
  }

  /**
   * Returns the reference clock value (value of SystemClock.elapsedRealtime())
   * corresponding to the NTP time.
   *
   * @return reference clock corresponding to the NTP time.
   */
  public long getNtpTimeReference() {
    return mNtpTimeReference;
  }

  /**
   * Returns the round trip time of the NTP transaction
   *
   * @return round trip time in milliseconds.
   */
  public long getRoundTripTime() {
    return mRoundTripTime;
  }

  /**
   * Reads an unsigned 32 bit big endian number from the given offset in the buffer.
   */
  private long read32(byte[] buffer, int offset) {
    byte b0 = buffer[offset];
    byte b1 = buffer[offset+1];
    byte b2 = buffer[offset+2];
    byte b3 = buffer[offset+3];

    // convert signed bytes to unsigned values
    int i0 = ((b0 & 0x80) == 0x80 ? (b0 & 0x7F) + 0x80 : b0);
    int i1 = ((b1 & 0x80) == 0x80 ? (b1 & 0x7F) + 0x80 : b1);
    int i2 = ((b2 & 0x80) == 0x80 ? (b2 & 0x7F) + 0x80 : b2);
    int i3 = ((b3 & 0x80) == 0x80 ? (b3 & 0x7F) + 0x80 : b3);

    return ((long)i0 << 24) + ((long)i1 << 16) + ((long)i2 << 8) + (long)i3;
  }

  /**
   * Reads the NTP time stamp at the given offset in the buffer and returns
   * it as a system time (milliseconds since January 1, 1970).
   */
  private long readTimeStamp(byte[] buffer, int offset) {
    long seconds = read32(buffer, offset);
    long fraction = read32(buffer, offset + 4);
    return ((seconds - OFFSET_1900_TO_1970) * 1000) + ((fraction * 1000L) / 0x100000000L);
  }

  /**
   * Writes system time (milliseconds since January 1, 1970) as an NTP time stamp
   * at the given offset in the buffer.
   */
  private void writeTimeStamp(byte[] buffer, int offset, long time) {
    long seconds = time / 1000L;
    long milliseconds = time - seconds * 1000L;
    seconds += OFFSET_1900_TO_1970;

    // write seconds in big endian format
    buffer[offset++] = (byte)(seconds >> 24);
    buffer[offset++] = (byte)(seconds >> 16);
    buffer[offset++] = (byte)(seconds >> 8);
    buffer[offset++] = (byte)(seconds >> 0);

    long fraction = milliseconds * 0x100000000L / 1000L;
    // write fraction in big endian format
    buffer[offset++] = (byte)(fraction >> 24);
    buffer[offset++] = (byte)(fraction >> 16);
    buffer[offset++] = (byte)(fraction >> 8);
    // low order bits should be random data
    buffer[offset++] = (byte)(Math.random() * 255.0);
  }
}
于 2019-09-27T09:37:46.237 に答える