How to get the current date / time, regardless of the device?

4

Well, I know that when you create an object of type Date: new Date() , the device's time and date is returned, so if I get into settings and change these values, then the time returned will be different from the universal time or local, correct.
How can I get a universal time and apply the region time zone?

    
asked by anonymous 05.05.2016 / 21:50

2 answers

7

If you have access to internet you can get the current date / time using a Public NTP Time Server.

Because access to the service is a network operation, it must be done in a thread other than UIThread. For this case it is best to use an IntentService.

TimeService.java

public class TimeService extends IntentService {

    public static final String RESULT_RECEIVER_EXTRA = "result_receiver_extra";
    public static final String RESULT_DATA_KEY = "result_data_key";
    public static final int SUCCESS_RESULT = 0;
    public static final int FAILURE_RESULT = 1;
    public static final String FAILURE_MESSAGE_KEY = "failure_message_key";

    private final String TIME_SERVER = "time.nist.gov";
    private ResultReceiver resultReceiver;

    public TimeService() {
        super("TimeService");
    }

    //Método para facilitar o uso do Service
    public static void requestTime(@NonNull Context context,
                                   @NonNull ResultReceiver resultReceiver) {

        Intent intent = new Intent(context, TimeService.class);
        intent.putExtra(RESULT_RECEIVER_EXTRA, resultReceiver);
        context.startService(intent);
    }

    @Override
    protected void onHandleIntent(@NonNull Intent intent) {

        resultReceiver = intent.getParcelableExtra(RESULT_RECEIVER_EXTRA);
        if(resultReceiver == null){
            throw new IllegalArgumentException("No ResultReceiver");
        }
        deliverResultToReceiver(getTime());
    }

    private TimeResult getTime(){

        NTPUDPClient timeClient = new NTPUDPClient();
        InetAddress inetAddress = null;
        try {
            inetAddress = InetAddress.getByName(TIME_SERVER);
        } catch (UnknownHostException e) {
            return new TimeResult(FAILURE_RESULT, -1, e.getMessage());
        }
        TimeInfo timeInfo = null;
        try {
            timeInfo = timeClient.getTime(inetAddress);
        } catch (IOException e) {
            return new TimeResult(FAILURE_RESULT, -1, e.getMessage());
        }
        long time = timeInfo.getMessage().getTransmitTimeStamp().getTime();
        return new TimeResult(SUCCESS_RESULT, time, "");
    }

    //Usa o ResultReceiver para enviar o resultado
    private void deliverResultToReceiver(TimeResult result){
        Bundle bundle = new Bundle();
        bundle.putString(FAILURE_MESSAGE_KEY, result.failureMessage);
        bundle.putLong(RESULT_DATA_KEY, result.time);
        resultReceiver.send(result.resultCode, bundle);
    }

    private class TimeResult{

        int resultCode;
        String failureMessage;
        long time;

        protected TimeResult(int resultCode, long time, String failureMessage){

            this.resultCode = resultCode;
            this.time = time;
            this.failureMessage = failureMessage;
        }
    }
}

The service, to communicate with the NTP Time Server, uses the class NTPUDPClient . It is necessary to indicate this dependency, so add

compile 'commons-net:commons-net:3.3'

in builder.gradle of the module.

To use the IntentService, use the

public static void requestTime(@NonNull Context context,
                               @NonNull ResultReceiver resultReceiver)

The service uses the resultReceiver object to communicate the result.

Example of an Activity to use the service.

TimeActivity.java

public class TimeActivity extends AppCompatActivity {

    private TextView tvResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_time);

        tvResult = (TextView)findViewById(R.id.tvResult);
    }

    public void onClickGetTime(View view) {
        tvResult.setText("Loading...");
        TimeService.requestTime(this, new TimeResultReceiver(new Handler(), this));
    }

    private static class TimeResultReceiver extends ResultReceiver {

        private WeakReference<TimeActivity> activityWeakReference;

        public TimeResultReceiver(Handler handler, TimeActivity activity) {
            super(handler);
            activityWeakReference = new WeakReference<>(activity);
        }

        @Override
        protected void onReceiveResult(int resultCode, @NonNull Bundle resultData) {

            TimeActivity activity = activityWeakReference.get();
            if (activity != null) {
                switch (resultCode)
                {
                    case TimeService.SUCCESS_RESULT:
                        long result = resultData.getLong(TimeService.RESULT_DATA_KEY);
                        activity.handleResult(result);
                        break;
                    case TimeService.FAILURE_RESULT:
                        String failureMassage = resultData.getString(TimeService.FAILURE_MESSAGE_KEY);
                        activity.handleFailure(failureMassage);
                        break;
                    default:
                        throw new IllegalArgumentException("Invalid result code");
                }
            }
        }

    }

    private void handleFailure(String failureMassage) {
        tvResult.setText("Error");
        Toast.makeText(this, failureMassage, Toast.LENGTH_SHORT).show();
    }

    private void handleResult(long result) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date resultDate = new Date(result);
        tvResult.setText(simpleDateFormat.format(resultDate));
    }
}

activity_time.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/btCalculate"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Get Time"
        android:onClick="onClickGetTime"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hora actual: "/>
        <TextView
            android:id="@+id/tvResult"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

</LinearLayout>

Notes:

Original response (*) .

If you have internet access, you can get the current time by going to link

public static Date getDateFromTimeapi_org() throws IOException{

    Date data = null;
    URLConnection conn = null;
    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");

    conn = new URL("http://www.timeapi.org/utc/now").openConnection();
    InputStream is = conn.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));

    try {

        data = dateFormat.parse(reader.readLine()); 

    } catch (java.text.ParseException e) {

        e.printStackTrace();
    }
    return data;
}

(*) At this time (2017/06/27) the service returns HTTP Error 404. The requested resource is not found.
As I do not know if it is a provisional or definitive situation I keep the original response.

    
06.05.2016 / 00:27
-1

In fact Date () is a timestamp, so internally it is already timestamp-independent . No need to pick up the date of another Internet service, because the date / time of the cell phone is usually the most accurate you can get (cell towers synchronize the time with GPS receivers).

Conversion to the local spindle only happens when it is converted to human readable format. Example:

// http://www.coderanch.com/t/417443/java/java/Convert-Date-timezone
DateFormat formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
formatter.setTimeZone(TimeZone.getTimeZone("CET"));
System.out.println(formatter.format(date));

Your problem might be that the user manually sets the time zone and it is different from the correct time zone to where it is at the time.

If this is a really serious problem, you can try using the Google Maps Time Zone API to get daylight savings time and latitude for a latitude and longitude (which you would get from your GPS device).

    
06.05.2016 / 03:17