【问题标题】:How can I get the current UTC time online in Android?如何在 Android 中在线获取当前的 UTC 时间?
【发布时间】:2012-07-24 20:10:15
【问题描述】:

我正在使用 UTC 时区和我的应用程序中的时间来获取数据。在应用程序中,用户可以在任何地方获取 UTC 时间并用于获取数据。 我用这个方法来获取UTC时间。

String format = "yyyy-MM-dd HH:mm:ss";
final SimpleDateFormat sdf = new SimpleDateFormat(format);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
String utcTime = sdf.format(new Date());

应用程序运行良好。但它正在将系统时间转换为 UTC 时间。问题是有时用户可以将时间更改为错误的时间。所以数据没有来。

上述问题的案例是:

例如,印度的当前日期时间是 2012 年 7 月 26 日星期四 14:27:56,加尔各答时区。那么太平洋时区的时间应该是 2012 年 7 月 26 日星期四 01:59:30 PDT。

但用户将其设备时间从 14:27:56 更改为 13:27:56,因此转换后的 UTC 时间将为 2012 年 7 月 26 日星期四 00:59:30 PDT。此时,由于一小时的差异,我的应用无法获取日期。

我不想使用 Java 的日期、日历类,也不想使用设备时间。如何在不涉及设备时间、日期的情况下直接获取 UTC 时间。是否有任何开源 API?

提前致谢。

【问题讨论】:

    标签: android timezone


    【解决方案1】:
    long dateInMillis = System.currentTimeMillis();
    

    这将返回自 1970 年 1 月 1 日 00:00:00 UTC 以来的毫秒数。

    然后只需将其解析为您想要的最合适的格式:

    String format = "yyyy-MM-dd HH:mm:ss";
    final SimpleDateFormat sdf = new SimpleDateFormat(format);
    
    String dateString = sdf.format(new Date(dateInMillis)));
    

    【讨论】:

    • 能否请您建议我如何将毫秒解析为 UTC 当前时间
    • 使用 java.util.Date 类。 "新日期(timeInMili);"
    • 我试过了。请在我的问题上阅读“上述问题的案例是:”。如果设备时间正确则返回正确的 UTC 时间,否则显示错误
    【解决方案2】:

    您可以使用Joda 库来操作日期/时间数据

    【讨论】:

      【解决方案3】:

      使用http://www.worldweatheronline.com/ 的免费 API,您可以通过 java 执行 HTTP GET 以获取 UTC 的当前时间 (http://www.worldweatheronline.com/time-zone-api.aspx)

      【讨论】:

        【解决方案4】:

        我认为您必须实现一个 Sntp 客户端并访问 NTP 以获取网络时间。 我的代码:

        import java.net.DatagramPacket;
        import java.net.DatagramSocket;
        import java.net.InetAddress;
        import java.util.Date;
        
        public class GetTime {
        
            public static void main(String[] args) {
                SntpClient client = new SntpClient();
                if (client.requestTime("pool.ntp.org", 30000)) {
                    long now = client.getNtpTime() + System.nanoTime() / 1000
                            - client.getNtpTimeReference();
                    Date current = new Date(now);
                    System.out.println(current.toString());
                }
        
            }
        }
        
        class SntpClient {
        
            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) {
                try {
                    DatagramSocket 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 = System.nanoTime() / 1000;
                    writeTimeStamp(buffer, TRANSMIT_TIME_OFFSET, requestTime);
        
                    socket.send(request);
        
                    // read the response
                    DatagramPacket response = new DatagramPacket(buffer, buffer.length);
                    socket.receive(response);
                    long responseTicks = System.nanoTime() / 1000;
                    long responseTime = requestTime + (responseTicks - requestTicks);
                    socket.close();
        
                    // 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 (Config.LOGD) Log.d(TAG, "round trip: " + roundTripTime +
                    // " ms");
                    // if (Config.LOGD) 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) {
        
                    return false;
                }
        
                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);
            }
        }
        

        希望对你有帮助。

        【讨论】:

          【解决方案5】:

          如果系统时间发生更改,则上述 SntpClient 上的 UTC 时间不起作用,例如手动8小时。因为它使用 System.currentTimeMillis 返回错误值!!!

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

          最好使用这个类从 NTP 服务器获取正确的 UTC 时间:

          import java.net.DatagramPacket;
          import java.net.DatagramSocket;
          import java.net.InetAddress;
          
          
          class NTP_UTC_Time
          {
          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(String host, int timeout) {
              try {
                  DatagramSocket 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);
          
                  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);
                  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);             
          }
          
          }
          

          并将其用于:

                  long now = 0;
          
                  NTP_UTC_Time client = new NTP_UTC_Time();
          
                  if (client.requestTime("pool.ntp.org", 2000)) {              
                    now = client.getNtpTime();
                  }
          

          如果您需要 UTC 时间“现在”作为 DateTimeString 使用函数:

          private String get_UTC_Datetime_from_timestamp(long timeStamp){
          
              try{
          
                  Calendar cal = Calendar.getInstance();
                  TimeZone tz = cal.getTimeZone();
          
                  int tzt = tz.getOffset(System.currentTimeMillis());
          
                  timeStamp -= tzt;
          
                  // DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss",Locale.getDefault());
                  DateFormat sdf = new SimpleDateFormat();
                  Date netDate = (new Date(timeStamp));
                  return sdf.format(netDate);
              }
              catch(Exception ex){
                  return "";
               }
              } 
          

          并将其用于:

          String UTC_DateTime = get_UTC_Datetime_from_timestamp(now);
          

          【讨论】:

          • 不要忘记使用权限:互联网
          • NTP_UTC_Time.writeTimeStamp,为什么要增加偏移量并将其存储到局部变量ofs?由于缓冲区大小为 48,所以不会写入索引 41 到 48,导致缓冲区溢出吗?
          【解决方案6】:
          class GetUTCTime : AppCompatActivity() {
          
          
          private val OUTPUT_DATE_FORMATE = "dd-MM-yyyy - hh:mm a"
          
          internal lateinit var textView : TextView
          
          
          val utcTime: String
              get() {
          
                  LongOperation().execute("")
          
                  return ""
              }
          
          override fun onCreate(savedInstanceState: Bundle?) {
              super.onCreate(savedInstanceState)
              setContentView(R.layout.activity_get_utctime)
          
              //        Log.d("UTC", "onCreate: "+ getUTCTime());
          
              textView = findViewById(R.id.dateTime)
          
              findViewById<View>(R.id.fetchButton).setOnClickListener {
                  utcTime
                  textView.text = "Fetching..."
              }
          }
          
          
          private inner class LongOperation : AsyncTask<String, Void, Long>() {
          
              override fun doInBackground(vararg params: String): Long? {
                  var nowAsPerDeviceTimeZone: Long = 0
                  try {
                      val sntpClient = SntpClient()
          
                      if (sntpClient.requestTime("ntp.ubuntu.com", 30000)) {
                          nowAsPerDeviceTimeZone = sntpClient.ntpTime
          
          
                      }
                      Thread.sleep(1000)
                  } catch (e: InterruptedException) {
                      Thread.interrupted()
                  }
          
                  return nowAsPerDeviceTimeZone
              }
          
              override fun onPostExecute(nowAsPerDeviceTimeZone: Long?) {
                  // might want to change "executed" for the returned string passed
                  // into onPostExecute() but that is upto you
          
                  Log.d("GMT", "getUTCTime:0 " + Date(nowAsPerDeviceTimeZone!!))
                  textView.text = Date(nowAsPerDeviceTimeZone).toString()
          
                  //            Calendar cal = Calendar.getInstance();
                  //            TimeZone timeZoneInDevice = cal.getTimeZone();
                  //            int differentialOfTimeZones = timeZoneInDevice.getOffset(System.currentTimeMillis());
                  //            nowAsPerDeviceTimeZone -= differentialOfTimeZones;
                  //
                  //
                  //
                  //
                  //
                  //            Log.d("GMT", "getUTCTime:1 "+ new Date(nowAsPerDeviceTimeZone).toString());
              }
          
              override fun onPreExecute() {}
          
              override fun onProgressUpdate(vararg values: Void) {}
          }
          

          }

          Find the SntpClient here

          【讨论】:

            【解决方案7】:

            对于 android,如果您尝试从主线程连接到 Internet,应用程序将崩溃,因此我编辑了代码以在 android 上正常工作

            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);
                }
            
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-03-20
              • 2011-02-18
              • 2013-09-29
              • 1970-01-01
              • 1970-01-01
              • 2017-02-15
              • 2010-09-23
              相关资源
              最近更新 更多