【问题标题】:If user change date and time in device then how to get current date and time in android?如果用户在设备中更改日期和时间,那么如何在 android 中获取当前日期和时间?
【发布时间】:2015-10-31 17:40:25
【问题描述】:

如果任何用户更改他/她设备中的日期和时间,那么如何获取实际运行的当前日期和时间。我正在开发一个使用当前日期作为开始日期的项目,所以如果用户根据需要更改他/她的日期,那么如果设备日期在之前或之后,它的自定义日期将是我的开始日期,而不是我想要的当前日期.

例如。现在当前日期是 2015 年 8 月 8 日,然后用户将他/她的设备日期更改为 2015 年 8 月 20 日,那么我如何才能获得 2015 年 8 月 8 日的实际日期?提前谢谢你...

【问题讨论】:

  • 您的应用是离线使用还是在线使用??
  • 您需要什么格式的时间? UTC 还是设备所在的实际时区?
  • @VivekSinha.. 是的,它在线...
  • @Squonk.. 设备当前所在的实际时区

标签: android date time timezone


【解决方案1】:

连接到 NTP 服务器:

import android.os.AsyncTask;

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


public class NTPUTCTime {
    private static final String TAG = "SntpClient";

    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;

    private long mNtpTime;

    public boolean requestTime() {
        try {
            new AsyncTask<Void, Void, Boolean>() {
                @Override
                protected Boolean doInBackground(Void... voids) {
                    try {
                        DatagramSocket socket = new DatagramSocket();
                        socket.setSoTimeout(1000);
                        InetAddress address = InetAddress.getByName("pool.ntp.org");
                        byte[] buffer = new byte[NTP_PACKET_SIZE];
                        DatagramPacket request = new DatagramPacket(buffer, buffer.length, address, NTP_PORT);
                        buffer[0] = NTP_MODE_CLIENT | (NTP_VERSION << 3);

                        writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET);

                        socket.send(request);

                        // read the response
                        DatagramPacket response = new DatagramPacket(buffer, buffer.length);
                        socket.receive(response);
                        socket.close();

                        mNtpTime = readTimeStamp(buffer, RECEIVE_TIME_OFFSET);
                    } catch (Exception e) {
                        //  if (Config.LOGD) Log.d(TAG, "request time failed: " + e);
                        e.printStackTrace();
                        return false;
                    }
                    return true;
                }
            }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR).get();

        } catch (Exception e) {
            //  if (Config.LOGD) Log.d(TAG, "request time failed: " + e);
            e.printStackTrace();
            return false;
        }

        return true;
    }


    public long getNtpTime() {
        return mNtpTime;
    }


    /**
     * 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 0 as NTP starttime stamp in the buffer. --> Then NTP returns Time OFFSET since 1900
     */
    private void writeTimeStamp(byte[] buffer, int offset) {
        int ofs = offset++;

        for (int i = ofs; i < (ofs + 8); i++)
            buffer[i] = (byte) (0);
    }

}

或者你可以使用这个库

https://github.com/instacart/truetime-android

【讨论】:

    【解决方案2】:

    user2629865 的回答大部分是正确的。您需要使用 SNTP(简单网络时间协议)之类的东西来连接到受信任的 Internet 时间服务器。

    如果用户也将时区更改为不正确的时区,就会出现问题。

    在您的情况下这是一个问题的原因是 NTP 和 SNTP 以 UTC 格式检索时间,这在一种方面很好,但显然不会根据设备地理位置为您提供“本地”时间。此时,您需要查看地理位置服务以尝试识别位置和时区,以获得准确的本地日期/时间。

    简而言之,没有简单的一步解决方案,最终归结为为什么您需要这样做。如果用户希望在他们自己的设备上搞乱他们的日期/时间/时区设置,那是他们的选择。

    【讨论】:

      【解决方案3】:

      类似于How can I get the actual date and time if the device date and time are inaccurate?

      使用时间服务器 - 这将是最好的方法。或者无论您拥有什么后端,在应用程序启动时公开一个 API 以获取服务器时间,然后如果除了 Date 之外还需要 hh:mm:ss,您可以使用 Timer 在整个会话期间跟踪时间。

      【讨论】:

      • 我想要安卓而不是ios。我知道我已经看到了,但我不知道如何使用它。
      • 平台无关紧要:使用时间服务器(为Android编写相应的Java代码)或公开API将允许您同步时间。如果没有服务器,如果设备时间不正确,您将无法调整时间。您需要与服务器同步。如果您的应用程序在启动时具有与服务器时间同步的客户端-服务器交互。这也是 Android 同步时间的方式 - stackoverflow.com/questions/14381005/…。使用任何公共 ntp - pool.ntp.org/en
      猜你喜欢
      • 1970-01-01
      • 2015-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-03
      • 2019-08-13
      • 2017-10-05
      相关资源
      最近更新 更多