长期在US,大半年不更新博客了,现在有空吧自己和团队一些开发过程中遇到的问题和解决方案分享出来。
现象:
这里我们讲,在前端,我们用Extjs的DateField来让用户选择日期,
- items:[
- {
- xtype:'displayfield',
- margin:'20 0 0 15',
- id:'appEnvShow',
- value:'What is your expected golive date for this <b>[Dev]</b> environment'
- },
- {
- xtype:'datefield',
- format:'m/d/Y',
- allowBlank:false,
- emptyText:'mm/dd/yyyy',
- margin:'10 0 0 15',
- width:100,
- selectOnFocus:true,
- minValue:new Date(),
- name:'goliveDate'
- }
- ]
然后在我们收集所有数据并且构建json对象时候,我们一开始传递的是对应这个日期的long类型,如下,见我特别加粗的代码行17-19:
- Ext.define('envprovision.controller.Envprovision', {
- extend: 'Ext.app.Controller',
- init: function() {
- var scope = this;
- this.serviceCheckedArr = [];
- this.control({
- 'button[name=btnNextInDefineApp]':{
- click:function(btn){
- var form = btn.up('[name=sbumitform]');
- if(form.getForm().isValid()){
- var paraObj = form.getValues();
- var appInfoJSONData = {};
- for(var index in paraObj){
- if(index !='title' && index !='url'){
- appInfoJSONData[index] = paraObj[index];
- }
- if(index == 'goliveDate'){
- appInfoJSONData[index] = Date.parse(appInfoJSONData[index]);
- }
- }
- var titleArr = paraObj.title;
- var urlArr =paraObj.url;
这样导致的结果是每次当用户选择一个日期时候,这个long类型我们到后端java程序用这个long类型来构造java.util.Date类型时候,得到的日期如果转化为GMT 时间,总比我们传递过来的时间少一天。
比如说,我们从DateField中选择的日期是2-22-2013 ,那么我们打开Firebug调试后,会发现实际这个日期对应的long值为1361462400000,然后我们用这个long值来构造java.util.Date(),并且转为GMT时间,如下:
- Date d = new Date(1361462400000L);
- System.out.println(d.toGMTString());
结果显示的是 21 Feb 2013 16:00:00 GMT
结论:
开始,我和我们团队的人都认为这个是因为Ext-js的Date(实际是javascript的Date)和java.util.Date基于的标准时间不一样,后来我们查阅了文档,发现文档中说,这2个日期都是基于GMT 的1970年1月1日0时0分0秒,后来我们网上搜了些文章,发现很多人都报告了这个是一个BUG.比如:
http://www.sencha.com/forum/archive/index.php/t-62250.html
解决方法:
既然传递long值存在不一致的问题,那么最保险的做法就是不传递long值而是只传递对应的String值,比如我们在ext-js中,我们让这个组件不传递long值,也就是注释掉controller的被我highlight的17-19行,这样,传递到json payload中的值就是02/22/2013这样的字符串,然后我们在java程序中,从字符串中分离出年,月,日,然后构造java.util.Date():
- public long getLongGoliveDate(){
- String goliveDate = getGoliveDate();
- int month = Integer.parseInt(goliveDate.substring(0,goliveDate.indexOf("/")) );
- int day= Integer.parseInt(goliveDate.substring(goliveDate.indexOf("/")+1,goliveDate.lastIndexOf("/")) );
- int year= Integer.parseInt(goliveDate.substring(goliveDate.lastIndexOf("/")+1,goliveDate.length()) );
- Date date = new Date(year-1900,month-1,day);
- return date.getTime();
- }
这样得到的date.getTime()对应的long类型就准确无误了,可以参与任何计算,最后如果要吧结果返回到客户端的时候,只要再反转为字符串类型就没问题了。