在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