Android与服务器通讯:如何保证两端时间一致性

在AChat项目的开发过程中,项目要求无论终端是什么时区设置、地处何方,终端的时间是否正确,post到服务器的数据包里面的时间字段均要求跟服务器同步,也就是说,用户买来一部新手机、新平板,不做任何日期时间、时区方面的设置,装了App就用,也能让时间数据正确。

我是这样设计的,在app的setting中有3个变量org_tablet_tm,org_server_tm和server_timezone,App启动的时候,即联线服务器取回当时的时间和服务器所在时区分别保存在org_server_tm和server_timezone,同一刻,取终端的时间保存在org_tablet_tm。

定义now()函数,此函数取当前设备时间再加上org_server_tm-org_tablet_tm的差值。

	/**
	 * 永远以server为准
	 * @return
	 */
	public static Date now(){
		Date w_ret=new Date();
		w_ret.setTime(w_ret.getTime()+(org_server_tm-org_tablet_tm));
		return w_ret;
	}

好了,这时候尽管设备终端的时间乱七八糟,只要时区跟服务器时区一致,用now()函数即可获得服务器上此时此刻的时间。

但是,问题来了,每个用户的终端设备时区不一定跟服务器上的一致,有可能他们根本没调时间、或没勾上自动同步时间,这时候需要我们用代码实现在终端不同时区也能跟服务器上的时间同步。

先看看这个DateTimeConvertToServer这个函数,先从tm中减去当前时区跟格林威治之间的时间差,再加上服务器所在时区跟格林威治时间差,即可算出到服务器时间:

	/***
	 * 把当地的时间转为服务器当时的时间,一般递交数据前先把Date一类数据转换
	 * @param tm
	 * @return
	 */
	public static Date DateTimeConvertToServer(Date tm){
		if (tm==null)return null;
		tm=new Date(tm.getTime()-getDiffTimeZoneRawOffsetStd(TimeZone.getDefault().getID())); //转成格林威治时间
		Date d=new Date(tm.getTime()+getDiffTimeZoneRawOffsetStd(server_timezone));
		return d;
	}

再看getDiffTimeZoneRawOffsetStd函数,用于计算指定时区跟格林威治时区的时间差(毫秒):

	/***
	 * 计算出指定时区跟格林威治时间差
	 * @param timeZoneId
	 * @return
	 */
	public static int getDiffTimeZoneRawOffsetStd(String timeZoneId) {
        //return TimeZone.getTimeZone(timeZoneId).getRawOffset();
		TimeZone tz = TimeZone.getTimeZone(timeZoneId);
	    return tz.getOffset(GregorianCalendar.getInstance(tz).getTimeInMillis());
	}

我在参数里面配置一个选项”是否转换成终端时间“,若转换,则什么都不做,因为Android系统能根据当前设置的时区自动转换时间,若不转换,则显示服务器端时间,则需要用DateTimeConvertToServer函数转换一下。

==================================

完结前吐槽一下,网络上流传一段时区差的计算函数,它们用TimeZone的getRawOffset,当时我也抄来用,各种时区试一遍,开始是各种适合,但测试到Asia/Baku时顿时石化了,同样是东5区的卡拉奇、乌拉尔都没问题,自巴库起开始一路往西的时区都相差一小时!!!用getRawOffset获得巴库离格林威治差4小时,但应该是5小时!!由于时间问题没仔细分析什么原因,有空再看并。

转载请注明出处:http://blog.csdn.net/rocklee

时间: 2024-10-17 08:34:03

Android与服务器通讯:如何保证两端时间一致性的相关文章

时间服务器通讯协议

目录 第1章通讯协议    1 1.1 RFC-868    1 1.2 time/UDP    2 1.3 NTP    3 1.3.1 客户端给服务器发送请求    3 1.3.2 服务器给客户端的回复    5 1.3.3 网络延时    5 第1章通讯协议 通过访问时间服务器,就可以获得精准的时间.Windows7自带访问时间服务器的功能,如下图所示: 这里就存在一个问题了:如何才能获得时间服务器time.windows.com上的时间?这就需要了解时间服务器的通讯协议了. 1.1 RF

如何实现android和服务器长连接

转载 这种功能实际上就是数据同步,同时要考虑手机本身.电量.网络流量等等限制因素,所以通常在移动端上有一下两个解决方案: 1.一种是定时去server查询数据,通常是使用HTTP协议来访问web服务器,称Polling(轮询): 2.还有一种是移动端和服务器建立长连接,使用XMPP长连接,称Push(推送). 从耗费的电量.流量和数据延迟性各方面来说,Push有明显的优势.但是使用Push的缺点是: 对于客户端:实现和维护相对成本高,在移动无线网络下维护长连接,相对有一些技术上的开发难度. 对于

Android 心跳包心跳连接 如何实现android和服务器长连接呢?推送消息的原理

前言:现在的大多数移动端应用都有实时得到消息的能力,简单来说,有发送消息的主动权和接受消息的被动权.例如:微信,QQ,天气预报等等,相信好处和用户体验相信大家都知道吧. 提出问题:这种功能必须涉及client(客户端)和server(服务器),所以到底client如何和server实现实时连接通讯? 分析问题:这种功能实际上就是数据同步,同时要考虑手机本身.电量.网络流量等等限制因素,所以通常在移动端上有一下两个解决方案:1.一种是定时去server查询数据,通常是使用HTTP协议来访问web服

网络--三种网络通讯方式及Android的网络通讯机制

Android平台有三种网络接口可以使用,他们分别是:java.net.*(标准Java接口).Org.apache接口和Android.net.*(Android网络接口).下面分别介绍这些接口的功能和作用. 1.标准Java接口 java.net.*提供与联网有关的类,包括流.数据包套接字(socket).Internet协议.常见Http处理等.比如:创建URL,以及URLConnection/HttpURLConnection对象.设置链接参数.链接到服务器.向服务器写数据.从服务器读取

[Android]Samba服务器在Ubuntu下的配置与Windows系统间的数据共享

安装Samba 安装sambasudo apt-get install samba[编辑]Kubuntu 安装系统设置的共享模块sudo apt-get install kdenetwork-filesharing[编辑]配置 1.windows 访问 ubuntu 第一步创建共享目录: 比如要创建/home/用户名/share首先创建这个文件夹 (这个用户名就是你的用户名,为了方便易懂我才这样写的,到时记得自己改啊) 代码:mkdir /home/用户名/share (新建share文件夹)c

Android中通过反射来设置显示时间

这个Toast的显示在Android中的用途还是很大的,同时我们也知道toast显示的时间是不可控的,我们只能修改他的显示样式和显示的位置,虽然他提供了一个显示时间的设置方法,但是那是没有效果的(后面会说到),他有两个静态的常量Toast.SHORT和Toast.LONG,这个在后面我会在源码中看到这个两个时间其实是2.5s和3s.那么我们如果真想控制toast的显示时间该怎么办呢?真的是无计可施了吗?天无绝人之路,而且Linux之父曾经说过:遇到问题就去看那个操蛋的源代码吧!!下面就从源代码开

Android 与服务器的通信方式

- Android 与服务器的通信方式主要有两种,一种是http 通信 ,一种是socket 通信. 两者的最大差异在于,http连接使用的是“请求—响应方式”,即在请求时建立连接通道,当客户端向服务器发送请求后,服务器端才能向客户端返回数据.而Socket通信则是在双方建立起连接后就可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端想服务器发送请求. 那么,什么是socket?Socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信.通过建立socket连接

Android进阶笔记04:Android进程间通讯之Messenger ( 区别于AIDL)

一. Android进程间通讯之Messenger 的引入 (1)引言:      平时一说进程间通讯,大家都会想到AIDL,其实messenger和AIDL作用一样,都可以进行进程间通讯.它是基于消息的进程间通信,就像子线程和UI线程发送消息那样,是不是很简单,还不用去写AIDL文件,是不是有点小爽.哈哈.此外,还支持记录客户端对象的Messenger,然后可以实现一对多的通信:甚至作为一个转接处,任意两个进程都能通过服务端进行通信. (2) Messenger 与 AIDL 比较:    

Android 通过应用设置系统日期和时间的方法

android 2.3 android 4.0 测试可行,不过需要ROOT权限. import java.io.DataOutputStream; import java.io.File; import java.io.IOException; import java.util.Calendar; import android.os.SystemClock; public class SystemDateTime { static final String TAG = "SystemDateTi