这是当时还在穆sir手下干活的时候遇到的一个问题,是我的第一篇技术博文,虽然现在看起来so easy..


使用GWT & GAE for Java,需要在数据库中存进去一个Date,表示存储的时刻,在根据用户选择的时间选择对应的数据。

设计的是用户粗略的根据日期来选择范围,时分秒都不考虑。用了DatePicker和几个TextBox的组合,没有用DateBox,因为觉得DateBox对于选取略久以前的时间就不够方便了。DatePicker返回的时间时分秒是默认的,12:00:00(PS:我觉得设成这个时间,对于任何一个时区都可以保证DAY_OF_MONTH一致)

但是调试的时候才发现这么做有个问题!TimeZone!存进去一个Date date = new Date()。在本地的时候TimeZone一般会根据系统设置而自动设好,比如GMT+8,而在GWT/GAE这里,可以在查看数据库知道,全部存成UTC、0时区!用户选择的时间又是东八区的时间,于是会有误差,找不准数据。

所以需要GregorianCalendar来确定时区!

此外还需要展示最初始数据的时间和最后的时间,而GregorianCalendar在GWT的client端又用不了,所以我就放到了server端,client通过发RPC拿回展示时间的String。

server端,要通过Date生成GregorianCalendar,我没有看到直接通过Date作为参数的构造函数,所以就用了GregorianCalendar(int year, int month, int day, int hour, intminute, int second)

在本地JUnit测试的时候也一如预想,使用setTimeZone(TimeZone.getTimeZone(“GMT+8”))。之后再calendar.get()就可以拿到对应时区的时间(PS:在Calendar中setTimeZone()对于其内部存着的long型数据是没有影响的,只是在get()的时候会算上偏移量而已)。但是!在GWT上运行的时候却就是没有作用,setTimeZone(),然后却没有变成新时区的时间!具体原因我还不知道。

正好测试setTimeZone对long型millitime的影响的时候有了灵感,直接calendar.setTimeInMillis(date.getTime())!这样setTimeZone()什么的也有反应了!具体原因我还是不知道…

Stackoverflow上的一个相关问题

这里说的蛮好“treatall dates as milliseconds since epoch in GMT timezone”,要用的时候自己按不同时区解析下就好了。

几天之后,经过尝试,发现:在client端要显示时间的话,直接用GWT给的DateTimeFormat,只要getFormat(“yyyy年MM月dd日 HH:mm:ss”)这样去自己定义就可以了,打印出来的结果是“2011年07月22日 21:53:39”

但是DateTimeFormat只是显示的好用,我要比较还是的自己在server端Calendar来比啊

PS:DateTimeFormat只能在client端使用,在server和shared端使用都会报 java.lang.ExceptionInInitializerError 的Exception,用JUnit一试就知道了

java.lang.ExceptionInInitializerError 
    at com.google.gwt.i18n.client.DateTimeFormat.getDefaultDateTimeFormatInfo(DateTimeFormat.java:839)
    at com.google.gwt.i18n.client.DateTimeFormat.getFormat(DateTimeFormat.java:519)
    at com.google.gwt.i18n.client.DateTimeFormat.getFullDateFormat(DateTimeFormat.java:669)
    at edu.tongji.sc.PHR.shared.TestDate.test(TestDate.java:12)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.UnsupportedOperationException: ERROR: GWT.create() is only usable in client code!  It cannot be called, for example, from server code.  If you are running a unit test, check that your test case extends GWTTestCase and that GWT.create() is not called from within an initializer or constructor.
    at com.google.gwt.core.client.GWT.create(GWT.java:92)
    at com.google.gwt.i18n.client.LocaleInfo.<clinit>(LocaleInfo.java:36)
    ... 26 more