Raghu Mudem
Raghu Mudem

Reputation: 6963

How can I get the current UTC time online in Android?

I am using the UTC timezone and the time in my application to get data. In the application, wherever the user can get the UTC time and used for getting the data. I used this method to get the UTC time.

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

The application is working fine. But it is converting the system time to UTC time. The problem is that sometimes the user can change the time to the wrong time. So the data is not coming.

Case for the above issue is:

For example the current date time in India is Thursday, 26 July 2012, 14:27:56, time zone Kolkata. Then the time, Pacific time zone, should be Thursday, 26 July 2012, 01:59:30 PDT.

But the user changed his device time from 14:27:56 to 13:27:56, so the converted UTC time will be Thursday, 26 July 2012, 00:59:30 PDT. At this point my app is not able to get the date because of the one-hour difference.

I don't want to use date, Calendar classes for Java and I don't want to use the device time. How can I get the UTC time directly, without involving the device's time, date. Is there any open-source API for that?

Thanks in advance.

Upvotes: 9

Views: 25417

Answers (7)

Momen Zaqout
Momen Zaqout

Reputation: 1498

For android, if you tried to connect to the Internet from the main thread the app will crash, so I edited to code to work correctly on 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);
    }

}

Upvotes: 0

labhya sharma
labhya sharma

Reputation: 47

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

Upvotes: -2

Ingo
Ingo

Reputation: 5381

UTC Time over SntpClient above don't work if the the Sytem time changed e.g. manually for 8 hours. Because it using System.currentTimeMillis wich returns the false value!!!

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

Better use this Class to get the right UTC Time from NTP Server:

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

}

And use it with:

        long now = 0;

        NTP_UTC_Time client = new NTP_UTC_Time();

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

If you need UTC Time "now" as DateTimeString use function:

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

and use it with:

String UTC_DateTime = get_UTC_Datetime_from_timestamp(now);

Upvotes: 6

enjoy-writing
enjoy-writing

Reputation: 520

I think you must implement a Sntp Client and access NTP to get network time. My code:

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

Hope that can help you.

Upvotes: 4

I&#241;igo
I&#241;igo

Reputation: 12823

long dateInMillis = System.currentTimeMillis();

This will return you the number of milliseconds since January 1, 1970 00:00:00 UTC.

Then just parse it to the most suitable format you want:

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

String dateString = sdf.format(new Date(dateInMillis)));

Upvotes: 5

Dnlhoust
Dnlhoust

Reputation: 118

Using the free API at http://www.worldweatheronline.com/, you can perform a HTTP GET via java to get the current time in UTC (http://www.worldweatheronline.com/time-zone-api.aspx)

Upvotes: 3

Alexander
Alexander

Reputation: 48242

You can use Joda library to manipulate date/time data

Upvotes: -1

Related Questions