如果任何用户在他/她的设备中更改日期和时间,那么如何获得实际运行的当前日期和时间。我正在研究一个项目,使用当前日期作为开始日期,所以如果用户改变他/她的日期,因为他想要,那么它的自定义日期将是我的开始日期,我想要当前日期的地方,如果设备日期是之前或之后。
交货。现在当前日期是2015年8月8日,然后用户将他/她的设备日期更改为2015年8月20日,那么我如何才能获得2015年8月8日的实际日期?
连接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类似于如何获取设备日期和时间不准确的实际日期和时间?
使用时间服务器——这将是最好的方法。或者无论你有什么后端,当应用程序启动时,公开一个API来获取服务器时间,然后你可以在整个会话期间使用Timer来保持时间,如果你需要hh:mm:ss,除了Date。
user2629865的答案大部分是正确的。您将需要使用类似SNTP(简单网络时间协议)的东西来连接到受信任的Internet时间服务器。
如果用户还将时区更改为不正确的时区,则会出现问题。
在您的情况下,这是一个问题的原因是NTP和SNTP以UTC格式检索时间,这在某种程度上是好的,但显然不会根据设备的地理位置获得"本地"时间。此时,您需要查看地理定位服务,以尝试识别位置和时区,以便获得准确的本地日期/时间。
简而言之,没有简单的一步答案,最终归结为为什么你需要这样做。如果用户希望在自己的设备上更改日期/时间/时区设置,那么这是他们的选择。