1. 程式人生 > >獲取網路時間、獲取特定時區時間、時間同步GMT UTC

獲取網路時間、獲取特定時區時間、時間同步GMT UTC

    <div class="markdown_views"><p><strong>方法一:</strong></p>
SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
dff.setTimeZone(TimeZone.getTimeZone("GMT+08"));  
String ee = dff.format(new Date());
  
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

這個方法獲取的結果是24小時制的,月份也正確。
這個方法不隨手機時間的變動而變動。也就是說,即使手機設定成別的時區,不是東八區,這個方法返回的也照樣是北京時間!!!這正是我在做專案的時候用到的方法!!徹底解決專案需求!

方法二:

Calendar calendar = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss");
sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
String rt = sdf.format
(calendar.getTime());
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

這個方法獲取的結果是不是24小時制的,月份也正確。

方法三:

public static String getLocalDatetimeString(String local) {  
   Calendar cal = new GregorianCalendar(TimeZone.getTimeZone(local));  
   cal.setTimeInMillis(Calendar.getInstance().getTimeInMillis());  
   String
date = cal.get(Calendar.YEAR) + "-" + (cal.get(Calendar.MONTH) + 1) + "-" + cal.get(Calendar.DAY_OF_MONTH); String time = cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND); return date + " " + time; } 方法呼叫: String tt = getLocalDatetimeString("GMT+8");
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

程式碼裡也看出來了,這個在月份上加了一個1, 24小時制

以上三種方法驗證如下:

import java.sql.Time;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;


public class TimeTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        method1();
        method2();
        method3();
    }

    static void method1(){
        SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
        dff.setTimeZone(TimeZone.getTimeZone("GMT+08"));  
        String ee = dff.format(new Date());
        System.out.println("ee="+ee);
    }

    static void method2(){
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss");
        sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        String rt = sdf.format(calendar.getTime());
        System.out.println("TimeTest.method2() rt="+rt);
    }
    static void method3(){
        String local = "GMT+8";
        Calendar cal = new GregorianCalendar(TimeZone.getTimeZone(local));  
        cal.setTimeInMillis(Calendar.getInstance().getTimeInMillis());  
        String date = cal.get(Calendar.YEAR) + "-" + (cal.get(Calendar.MONTH) + 1) + "-" + cal.get(Calendar.DAY_OF_MONTH);  
        String time = cal.get(Calendar.HOUR_OF_DAY) + ":" + cal.get(Calendar.MINUTE) + ":" + cal.get(Calendar.SECOND);  
        System.out.println("TimeTest.method3() date="+date+",time="+time);
    }

}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

結果如下:
這裡寫圖片描述

本人採用的是第一種方法,因為第一種方法的時間是不隨手機時間的設定而改變。
第二種方法也是可以的,不過時間小時是12進位制。

第四種方法:
網上還有這種方法獲取時間:

URL url=new URL("http://www.bjtime.cn");//取得資源物件
       URLConnection uc=url.openConnection();//生成連線物件
       uc.connect(); //發出連線
       long ld=uc.getDate(); //取得網站日期時間
       Date date=new Date(ld); //轉換為標準時間物件
       //分別取得時間中的小時,分鐘和秒,並輸出
       System.out.print(date.getHours()+"時"+date.getMinutes()+"分"+date.getSeconds()+"秒");
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

這種方式需要開啟一個執行緒獲取時間,同時也存在著一種風險就是由於網路問題,獲取不到響應的問題。還有一個重要的問題件就是這個時間的獲取會隨著手機時區的改變而改變。

方法五:

通過網路或者GPS的方式。
程式碼:
LocationManager locMan = (LocationManager) this.getSystemService(MainActivity.LOCATION_SERVICE);
//獲取最近一次知道的時間
long networkTS = locMan.getLastKnownLocation(LocationManager.NETWORK_PROVIDER).getTime();

或者實時的獲取時間:
locMan.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this); //獲取當前時間

當我們使用requestLocationUpdates時,我們需要實現LocationListener介面。
在LocationListen的回撥onLocationChanged當中獲取時間
@Override
public void onLocationChanged(Location location) {
// TODO Auto-generated method stub
long time = location.getTime();
Date date = new Date(time);
System.out.println(time + " NETWORK_PROVIDER " + date);
// System.out.println(STANDARD_TIME + " ");
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

這種方式是利用手機定位系統進行時間的獲取,但是這種方式會隨著手機的設定的時區的變動而改變。

第四種方式和第五種方式,我都在手機端進行了驗證,可以正常獲取時間。方式是沒有問題的。

既然有這麼多方法,大家看著那種方式適合自己的需求,選擇相應的方法。

我還是推薦第一種方法!簡單實用!!!!^_^

今天再在本文基礎上補充一些內容。現在我的專案中有這樣一種需求:就是播放視訊的時候,特別是監控視訊,我想要有時間限制,在一定時間內可以觀看,超出設定的時間,不能觀看。
Android端對於這樣的需求,上面的幾種方法都不行了,因為上面的方法都跟手機系統有關係了,當我改變手機系統的時間,時區等都會造成獲取的時間不對應,跟伺服器時間不對。怎麼辦呢?有辦法!!!
我是這樣做的,當獲取到資訊的時候,比如視訊節點資訊的時候,伺服器順帶著把伺服器當前的時間返回來,有了伺服器的時間,剩下的我就利用使用者操作的時間間隔,加上伺服器的時間不就是手機所在地當前的時間嗎?
那麼時間間隔怎麼算呢?請看下面的SystemClock類幾個方法:

1、System.currentTimeMillis()是一個標準的“牆”時鐘(時間和日期),表示從紀元到現在的毫秒數。該牆時鐘能夠被使用者或電話網路(見setCurrentTimeMillis(long))設定,所以該時間可能會向前或向後不可預知地跳越。該時鐘應該僅僅被使用在當現實世界的對應的日期和時間是重要的情況,例如一個日曆或鬧鐘應用程式。而間隔時間和經過時間應該使用不同的時鐘。如果你使用System.currentTimeMillis(),可以考慮監聽ACTION為ACTION_TIME_TICK、 ACTION_TIME_CHANGED、ACTION_TIMEZONE_CHANGED 的廣播去監聽時間變化。

2、uptimeMillis()表示自系統啟動時開始計數,以毫秒為單位。返回的是從系統啟動到現在這個過程中的處於非休眠期的時間。當系統進入深度睡眠時(CPU關閉,裝置變黑,等待外部輸入裝置)該時鐘會停止。但是該時鐘不會被時鐘調整,閒置或其他節能機所影響。這是大多數間隔時間的基本點,例如Thread.sleep(millls)、Object.wait(millis)和System.nanoTime()。該時鐘被保證是單調的,適用於檢測不包含休眠的間隔時間的情況。大多數的方法接受一個時間戳的值除了uptimeMillis()時鐘。

3、elapsedRealtime() and elapsedRealtimeNanos() 返回系統啟動到現在的時間,包含裝置深度休眠的時間。該時鐘被保證是單調的,即使CPU在省電模式下,該時間也會繼續計時。該時鐘可以被使用在當測量時間間隔可能跨越系統睡眠的時間段。

有幾種機制控制事件發生的時間:

1、標準的方法像Thread.sleep(millis) 和 Object.wait(millis)總是可用的,這些方法使用的是uptimeMillis()時鐘,如果裝置進入深度休眠,剩餘的時間將被推遲直到系統喚醒。這些同步方法可能被Thread.interrupt()中斷,並且你必須處理InterruptedException異常。

2、SystemClock.sleep(millis)是一個類似於Thread.sleep(millis)的實用方法,但是它忽略InterruptedException異常。使用該函式產生的延遲如果你不使用Thread.interrupt(),因為它會儲存執行緒的中斷狀態。

3、Handler可以在一個相對或者絕對的時間設定非同步回撥,Handler類物件也使用uptimeMillis()時鐘,而且需要一個loop(經常出現在GUI程式中)。

4、AlarmManager可以觸發一次或重複事件,即使裝置深度休眠或者應用程式沒有執行。事件可以選擇用 currentTimeMillis或者elapsedRealtime()(ELAPSED_REALTIME)來設定時間,當事件發生會觸發一個廣播。

方法:
1、public static long currentThreadTimeMillis () 返在當前執行緒執行的毫秒數。

2、public static long elapsedRealtime () 返回系統啟動到現在的毫秒數,包含休眠時間。

3、public static long elapsedRealtimeNanos () 返回系統啟動到現在的納秒數,包含休眠時間。

4、public static boolean setCurrentTimeMillis (long millis) 設定當前的”牆”時間,要求呼叫程序有許可許可權。返回是否成功。

5、public static void sleep (long ms) 等待給定的時間。和Thread.sleep(millis)類似,但是它不會丟擲InterruptedException異常。事件被推遲到下一個中斷操作。該方法直到指定的時間過去才返回。

6、public static long uptimeMillis () 返回系統啟動到現在的毫秒數,不包含休眠時間。就是說統計系統啟動到現在的非休眠期時間。

這些方法大家看看就知道啦。以上內容參考:http://www.2cto.com/kf/201403/288497.html

剩下的就是計算事件間隔了:
public static long elapsedRealtime () 返回系統啟動到現在的毫秒數,包含休眠時間
這個方法就可以計算從伺服器返回時間到使用者操作,播放視訊這一段時間的時間間隔。有個這個不就可以做到時間不受手機系統的限制了嗎?

/**
     * 
     * @param ts 形如yyyy-MM-dd hh:mm:ss
     * @param intervalTime  long型別
     * @return String HH:mm:ss
     */
    @SuppressLint("SimpleDateFormat")
    public static String getTime(String ts,long intervalTime){
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        Timestamp t=null;
        String tt="";
           try {
            t = new Timestamp(format.parse(ts).getTime());
            long ss = t.getTime();
            long st = ss+intervalTime;
            tt= getTime(st);
        } catch (java.text.ParseException e) {
            e.printStackTrace();
        }
        return tt;
    }
    /**
     * @param mis
     * @return HH:mm:ss
     */
    @SuppressLint("SimpleDateFormat")
    public static String getTime(long mis){
        SimpleDateFormat dff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String ee = dff.format(new Date(mis));
        return ee.substring(11);
    }
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

上面的方法中,
ts引數就是伺服器返回的當前時間,形如yyyy-MM-dd hh:mm:ss的字串
intervalTime引數,是獲取到伺服器響應到使用者進行操作的時間間隔,就是使用上面的elapsedRealtime ()方法獲取兩次時間計算得到。
方法的返回值String,形如 HH:mm:ss,這樣返回字串方便比較時間字元。由於視訊事件限制,就是時分秒,不可能涉及到年月日,所以這裡就是直接返回時分秒。

有了這個方法,完美解決了android APP與伺服器時間保持基本一致的需求。但是還是存在一定的問題的,因為伺服器返回時間不定,可能長可能短,所以時間並不會和伺服器的當前時間分秒不差,總會有延時,但是這個延時可以接受,大概最多在10秒左右。可以在時間間隔上稍微加一點就可以了。基本就滿足需求了。