Android advanced road - some chores about time

Last year, there was a need to synchronize the time of the two terminals (client and server). The reason was that the system time of the two terminals was inconsistent, resulting in time difference after the implementation of the demand, resulting in business errors. Therefore, I took the time to sort out the knowledge related to time and date~

Brothers

Before the official start, we should give priority to introducing the time zone. The 1884 international longitude conference divided the earth's surface into 24 zones according to the longitude, that is, based on the primary meridian, the range of 7.5 degrees of East-West longitude as the zero time zone, and then every 15 degrees as a time Zone, with a difference of one hour for each time zone

China's time zone spans five geographical time zones: East five, East six, East seven, East eight and East nine; Since 1949, the standard time in Chinese mainland, Taiwan, Hongkong and Macao is eight UTC+8 (East time), 8 hours faster than coordinated world time (UTC) or Greenwich standard time (GMT).

Due to historical and political factors, the above regions maintain their own time standards and timely area names

  • Chinese mainland's time standard: Beijing time (Beijing time zone is east eight district, 8 hours earlier than zero time zone. If the time of zero hour is 10 o'clock, then Beijing time is 18 points).

  • Taiwan's time standard is called Central Plains standard time or national standard time: Taiwan time or Taipei time

  • Time standard in Hong Kong: Hong Kong time

  • Macao standard time: Macao standard time

    The UTC time we usually see in the program is the time in the zero time zone. Its full name is Coordinated Universal Time, that is, world coordinated time. Another common abbreviation is GMT, that is, Greenwich mean time. Greenwich is located in the zero time zone. Therefore, the values of UTC time and GMT time are the same.

UTC (world standard time)

Coordinated Universal Time, also known as world standard time or world coordinated time, referred to as UTC (from English "Coordinated Universal Time" / French "Temps")
Universel Coordonn é) is the most important world time standard, which is based on atomic time seconds and as close to Greenwich mean time as possible.

GMT (Greenwich mean time)

Greenwich Mean time
Time (GMT) refers to the standard time at the Royal Greenwich Observatory in the suburbs of London, UK, because the prime meridian is defined as the longitude passing through there.

Theoretically, the noon of Greenwich mean time refers to the time when the sun crosses the Greenwich meridian (that is, when it is at the highest point over Greenwich);

Due to the uneven speed of the earth in its elliptical orbit, there may be an error between this time and the actual solar time, with a maximum error of 16 minutes

Because the earth's daily rotation is somewhat irregular and is slowing down slowly, Greenwich mean time is no longer used as standard time. The current standard time is coordinated universal time (UTC) which is annunciated by the atomic clock

CST (Beijing time)

Beijing time, China Standard Time. In terms of time zone division, it belongs to the eighth East Zone, which is 8 hours earlier than coordinated universal time and is recorded as UTC+8

However, the difficulty with the abbreviation CST is that it can represent four different times at the same time:
Central Standard Time (USA) UT-6:00
Central Standard Time (Australia) UT+9:30
China Standard Time UT+8:00
Cuba Standard Time UT-4:00

12. 24-hour system

The formatting time is 12 and 24 hours

 Date date=new Date();
 //Convert to time format 12 hour system
 SimpleDateFormat df_12=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
 //Convert to time format 24-hour system
 SimpleDateFormat df_24=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 
 System.out.println("12 Hour time:"+df_12.format(date));
 System.out.println("24 Hour time:"+df_24.format(date));

Output results

 12 Hour time:2017-12-07 03:55:04 
 24 Hour time:2017-12-07 15:55:04

Time update mechanism

Generally, the system time is automatically updated on the equipment. There are mainly the following two update mechanisms

NITZ

NITZ(Network Identity and Time Zone) is a mechanism for automatically configuring local time and date. At the same time, it also provides operator information to mobile devices through wireless networks

NITZ is an optional function in GSM since PHASE 2+ RELEASE 96. It is often used to automatically update the system clock of mobile phones

NITZ needs operator network support (through CS network). At present, domestic telecom and China Mobile support NITZ to update time and date, while China Unicom may not support it at present

NTP

NTP: NTP (Network Time Protocol) provides accurate time. First, there must be an accurate time source. This time should be the international standard time UTC.

The time source for NTP to obtain UTC can be atomic clock, observatory, satellite, or obtained from the Internet. In this way, there is an accurate and reliable time source. The time propagates according to the level of NTP server.

The difference between NTP and NITZ is that NTP needs to obtain time from a special NTP server. As long as the mobile phone is connected to the network, it can update the time.

Time zone processing

package com.nk.machine.model;

import java.text.DateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * @author MrLiu
 * @date 2020/9/24
 * desc
 */
public class TimeZoneTest {
    public static void main(String[] args) {
		//Test 3 methods for creating TimeZone objects
        showUsageOfTimeZones();
		//Test other API s for TimeZone
        testOtherAPIs();
		//Print all IDS supported by getTimeZone(String id)
		//printAllTimeZones() ;
    }

    /**
     * Test 3 methods for creating TimeZone objects
     */
    public static void showUsageOfTimeZones() {
        TimeZone tz;
        // (01) default time zone
        tz = TimeZone.getDefault();
        printDateIn(tz);
        // (02) set the time zone to "GMT+08:00"
        tz = TimeZone.getTimeZone("GMT+08:00");
        printDateIn(tz);
        // (03) set the time zone to ""
        tz = TimeZone.getTimeZone("Asia/Chongqing");
        printDateIn(tz);
    }

    /**
     * Print tz corresponding date / time
     */
    private static void printDateIn(TimeZone tz) {
        //The date is 14:22:30, September 19, 2013
        Date date = new Date(113, 8, 19, 14, 22, 30);
        // Gets the default DateFormat used to format Date
        DateFormat df = DateFormat.getInstance();
        // Set the time zone to tz
        df.setTimeZone(tz);
        // Gets the formatted string
        String str = df.format(date);
        System.out.println(tz.getID() + " :" + str);
    }

    /**
     * Test other API s for TimeZone
     */
    public static void testOtherAPIs() {
        // Default time zone
        TimeZone tz = TimeZone.getDefault();
        // Get 'id'
        String id = tz.getID();
        // Get display name
        String name = tz.getDisplayName();
        // Gets the time offset. The offset relative to the prime meridian, in ms.
        int offset = tz.getRawOffset();
        // Gets the hour corresponding to the time offset
        int gmt = offset / (3600 * 1000);

        System.out.printf("id=%s, name=%s, offset=%s(ms), gmt=%s\n",
                id, name, offset, gmt);
    }

    /**
     * Print all IDS supported by getTimeZone(String id)
     */
    public static void printAllTimeZones() {
        String[] ids = TimeZone.getAvailableIDs();
        for (String id : ids) {
            //int offset = TimeZone.getTimeZone(avaIds[i]).getRawOffset();
            //System.out.println(i+" "+avaIds[i]+" "+offset / (3600 * 1000) + "\t");
            System.out.printf(id + ", ");
        }
        System.out.println();
    }
}

Modify system time

Here: if you need to modify the system time, you need to set the machine root permission first, and relatively few scenarios are used

Andorid code

Method 1: getSystemService system service

 Calendar c = Calendar.getInstance();
 // Mm / DD / yyyy-1 H / min / S
 if (date != null) {
   int year = date.getYear() + 1900;
   int day = date.getDate();
   int month = date.getMonth();
   int hour = date.getHours();
   int minutes = date.getMinutes();
   int seconds = date.getSeconds();
   c.set(year, month, day, hour, minutes, seconds);
 }
 AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
 am.setTime(c.getTimeInMillis());

Method 2: DataOutputStream date input

        try {
            Process process = Runtime.getRuntime().exec("su");
            // Test setting time [time format]
            String datetime = "20131023.112800"; 
            // yyyyMMdd.HHmmss
            DataOutputStream os = new DataOutputStream(process
                    .getOutputStream());
            os.writeBytes("setprop persist.sys.timezone GMT\n");
            os.writeBytes("/system/bin/date -s "
                    + datetime + "\n");
            os.writeBytes("clock -w\n");
            os.writeBytes("exit\n");
            os.flush();
            Toast.makeText(MainActivity.this, "System time synchronization succeeded",Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            Toast.makeText(MainActivity.this,
                    "System time synchronization failed. There may be no synchronization ROOT jurisdiction?", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }

Mode three: call the cmd command in code.

    /**
     * @param cmd command
     */
    private static void execSuCmd(String cmd) {
        Process process = null;
        DataOutputStream os = null;
        DataInputStream is = null;
        try {
            process = Runtime.getRuntime().exec("su");
            os = new DataOutputStream(process.getOutputStream());
            os.writeBytes(cmd + "\n");
            os.writeBytes("exit\n");
            os.flush();
            int aa = process.waitFor();
            is = new DataInputStream(process.getInputStream());
            byte[] buffer = new byte[is.available()];
            is.read(buffer);
            String out = new String(buffer);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (os != null) {
                    os.close();
                }
                if (is != null) {
                    is.close();
                }
                if (process != null) {
                    process.destroy();
                }

            } catch (Exception e) {
            }
        }
    }

Call example

 String curr_time = "052514412019.52";
 execSuCmd("date " + curr_time + "\n busybox hwclock -w\n");

Extension: Android has a dedicated NetworkTimeUpdateServcie system service to update the system time. This service is created in SystemServer.java when the system is started

    if (!disableNetwork && !disableNetworkTime) {
        try {
            Slog.i(TAG, "NetworkTimeUpdateService");
            networkTimeUpdater = new NetworkTimeUpdateService(context);
       } catch (Throwable e) {
            reportWtf("starting NetworkTimeUpdate service", e);
        }
    }
    ...
    ...
    try {
        if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning();
    } catch (Throwable e) {
        reportWtf("Notifying NetworkTimeService running", e);
    }
cmd command

shell command

 #The format is date MMddHHmmyyyy.ss set
 date 123012002018.59 set

To use UTC time, you need to add the - u option

If you need to synchronize updates to the hardware RTC, you also need to use hwlock

usage: hwclock [-rswtluf]
# Commonly used
# Hwlock - w – from system time setting to hardware clock
# Hwlock - s – from hardware clock setting to system time

-f FILE Use specified device file instead of /dev/rtc (--rtc)
-l Hardware clock uses localtime (--localtime)
-r Show hardware clock time (--show)
-s Set system time from hardware clock (--hctosys)
-t Set the system time based on the current timezone (--systz)
-u Hardware clock uses UTC (--utc)
-w Set hardware clock from system time (--systohc)

Modify time zone

Set the time zone. The difference between new Date() and system time is 8 hours

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.TimeZone;

public class GetNowDate {
    //Get the current system time, string type
    public static String getStrDate() {
        SimpleDateFormat format= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //It is set as the East eighth district
        format.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        Date newDate = new Date();
        String dateStr = sdf.format(newDate);
        return dateStr;
    }

    //Get the current time Date type of the system. You need to convert the string type to time
    public static Date getDaDate() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //It is set as the East eighth district
        sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        Date date = new Date();
        String dateStr = sdf.format(date);

        //Convert string to time
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date newDate = null;
        try {
            newDate = df.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return newDate;
    }
}

Mutual conversion of time zone and time

SimpleDateFormat: conversion between Date and string, format time and parsing time

  //String to Date
  String stringDate = "Thu Oct 16 07:13:48 GMT 2015";
  SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM ddHH:mm:ss 'GMT' yyyy",Locale.US);
  Date date = sdf .parse(stringDate);
  System.out.println(date.toString());

  //Date to string
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    
  System.out.println(sdf .format(new Date()));

  //Format time
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
  String time = sdf.format(new Date());
  System.out.println(time);

  //Analysis time: 2016-01-05T15:06:58+0800
  Date date = sdf.parse(time);
  System.out.println(date);

  //T stands for time followed by Z stands for UTC unified time
  //Format time
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
  String time = sdf.format(new Date());
  System.out.println(time);

  //Analysis time: 2016-01-05T15:09:54Z
  Date date = sdf.parse(time);
  System.out.println(date);

Date: time zone, time conversion

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
 
public class TestTime {
	
public static void main(String[] args) {
	try {
        //Get the Date object and store the timestamp
        Date date = new Date();
        //Get timestamp (MS)
        long seconds = date.getTime();
        System.out.println("Current timestamp: " + seconds);
       
        //Current GMT (Greenwich mean) time, the time zone in which the current computer system is located
        SimpleDateFormat beijingFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("local(Dongba District)time: " + beijingFormat.format(date) +"; GMT time: " + date.toGMTString());
        
        //Dongba District time is converted to Dongjiu district (Tokyo) time, one hour earlier than Beijing
        SimpleDateFormat tokyoFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        tokyoFormat.setTimeZone(TimeZone.getTimeZone("Asia/Tokyo"));
        System.out.println("Tokyo(Dongjiu District)time: "+tokyoFormat.format(date));
        
        //Convert timestamp to Date
        SimpleDateFormat timestampFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String fotmatString = timestampFormat.format(seconds);
        Date parseDate = timestampFormat.parse(fotmatString);
        System.out.println("Timestamp converted to Date Time after: "+parseDate + ";Formatted: "+ fotmatString);
	            
	} catch (Exception e) {
		e.printStackTrace();
	}
}

Testlocaltime (Java 8 tool class)

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
 
public class TestLocalTime {
public static void main(String[] args) {
	//Gets the date in the current time zone
	LocalDate localDate = LocalDate.now();
	System.out.println("localDate: " + localDate);
	//time
	LocalTime localTime = LocalTime.now();
	System.out.println("localTime: " + localTime);
	//Get the date and time according to the above two objects
	LocalDateTime localDateTime = LocalDateTime.of(localDate,localTime);
	System.out.println("localDateTime: " + localDateTime);
	//Generate this object using static methods
	LocalDateTime localDateTime2 = LocalDateTime.now();
	System.out.println("localDateTime2: " + localDateTime2);
	//Format time
	DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");
	System.out.println("Time after formatting: " + localDateTime2.format(formatter));
	//Convert to timestamp (seconds)
	long epochSecond = localDateTime2.toEpochSecond(ZoneOffset.of("+8"));
	//Convert to milliseconds
	long epochMilli = localDateTime2.atZone(ZoneOffset.systemDefault()).toInstant().toEpochMilli();
	System.out.println("Timestamp is:(second) " + epochSecond + "; (millisecond): " + epochMilli);
	
	//The timestamp (in milliseconds) is converted to LocalDateTime
	Instant instant = Instant.ofEpochMilli(epochMilli);
	LocalDateTime localDateTime3 = LocalDateTime.ofInstant(instant, ZoneOffset.systemDefault());
	System.out.println("time stamp(millisecond)Convert into LocalDateTime: " + localDateTime3.format(formatter));
	//The timestamp (in seconds) is converted to LocalDateTime
	Instant instant2 = Instant.ofEpochSecond(epochSecond);
	LocalDateTime localDateTime4 = LocalDateTime.ofInstant(instant2, ZoneOffset.systemDefault());
	System.out.println("time stamp(second)Convert into LocalDateTime: " + localDateTime4.format(formatter));
	}
}

Turn off automatic synchronization to realize self-determined synchronization

After modifying the system, the time stamp has a time difference of 8 hours. After setting it first, the GMT+8 configuration of East No. 8 district can be adopted, which can be through the type mCalendar.setTimeZone(TimeZone.getTimeZone("GMT+8"); However, since the timestamp cannot be changed with the time zone, you can try to subtract the 8 * 60 * 60 * 100 time difference if there is a problem when setting the time

root permission, and add the following configuration in AndroidManifest.xml

<uses-permission android:name="android.permission.SET_TIME" />

Sample demo

    SimpleDateFormat format=new SimpleDateFormat("yyyyMMdd.HHmmss");
    //time is the timestamp obtained from the server
    Long t=new Long(time);
    t=t-8*60*60*1000;
    Date date=new Date(t);
    String datetime=format.format(date);
    try {  
        Process process = Runtime.getRuntime().exec("su");
        DataOutputStream os = new DataOutputStream(process.getOutputStream());  
        os.writeBytes("setprop persist.sys.timezone GMT\n");  
        //Set the time. This place must be in the form of yyyyMMdd.HHmmss
        os.writeBytes("/system/bin/date -s "+datetime+"\n");  
        os.writeBytes("clock -w\n");  
        os.writeBytes("exit\n");  
        os.flush(); 
    } catch (IOException e) {
        e.printStackTrace();
        return false;
    } 

Keywords: Android

Added by devarmagan on Sat, 11 Sep 2021 05:53:19 +0300