[color=blue]目标:面向多区域用户[/color]
添加更新记录:用户输入本区域时间, 数据库存储转换后的标准时间
查看记录: 数据库时间相同,view层根据用户区域显示相应的时间
说明本项目要求日期格式固定,不按照用户local显示. 如果要求按照用户local显示日期格式则需要使用如下的format, 可参考liferay源码
[color=blue]分析[/color]
liferay 提供了用户自定义zone (控制面板->setting->zone, 详见"liferay区域设置")。
页面显示时可以根据用户zone格式化取得的时间。
向后台发送数据时根据客户zone取得客户输入时间,转换为tomcat时间后再传入数据库
[color=red]原则(强烈建议[/color]
对于日期类型从后台向前台读取的过程中, 在business层不要做类型转换(例如试图转为long或String ), 只有在页面显示的时候才将其转为合适的日期格式和区域。
对于其他类型做同样的建议,如double, longtext,例如在business层中不要试图截取小数点位数和文本长度,在页面根据需要截取。如果业务上有特殊要求除外(如财务运算)
[color=blue]timezone 涉及的 web app 层次[/color]
1.view (jsp)
2.business(portletaction + service + finder/persistence)
//此处因为portlect负责读取输入的日期数据, finder负责写入日期数据,为方便说明timezone的传递,将其归入business层次, 勿纠结于层次划分
3.DB (mysql)
------------- [color=blue]util code[/color] -----------
DateUtil类提供公共方法获取包含用户时区和local的format
html/init.jsp提供公共format,包含用户zone和local 也可以直接使用DateUtil类提供的方法
html/init.jsp
------------- [color=blue] zone设置 [/color] -----------
用户A,leferay中设置 zone = GMT+7
TOMCAT zone = GMT+8
mysql zone = system = GMT+9
设定
用户试图输入日期 GMT+8 2013-01-01 12:00:00 保存至数据库
执行操作时web server 系统时间 GMT+8 2013-01-01 12:10:10
// web server 系统时区可任意设置,不影响以下结果
------------- [color=blue] 添加更新记录 [/color] -----------
[color=green]VIEW 层[/color]
用户A输入日期 " 2013-01-01 11:00:00",提交 (GMT+7)
[color=green]BUSINESS 层[/color]
获取页面输入日期,更新数据库
说明:
(1) dateFormatDateTime 的默认时区为用户时区GMT+7
(2) dateRead 获取时间为用户输入时间, 按照用户时区GMT+7转换为日期后再转换为tomcat时区GMT+8。
(3) new Date() 获取时间为 web server 系统时间, 时区为tomcat设置的时区GMT+8。
[color=red]注意:[/color]
ParamUtil.getDate(actionRequest, "date", dateFormatDateTime)方法实际隐含了两次转换
(1) 用户输入时间 2013-01-01 12:00:00,按用户时区(dateFormatDateTime) 转换为日期类型 GMT+7 2013-01-01 11:00:00
(2) GMT+7 2013-01-01 11:00:00 转换为tomcat时区 GMT+8 2013-01-01 12:00:00
[color=green]DB层[/color]
存储日期
数据库表中存储的dateInput和dateNew分别为
dateInput = 2013-01-01 12:00:00
dateNew = 2013-01-01 04:10:10
[color=red]注意:[/color]
数据库本身有时区定义,参见mysql时区定义。
mysql的时区定义会对now()获得字符串产生影响。
可以认为数据库存储的时间类型字段不包含时区信息,insert/update字符串即是所见字符串
例如:
传入参数:
dateInput = GMT+8 2013-01-01 12:00:00
dateNew = GMT+8 2013-01-01 12:10:10
mysql-〉 select dateInput, dateNew
结果: 2013-01-01 12:00:00 2013-01-01 12:10:10
传入参数:
dateInput = GMT+9 2013-01-01 12:00:00
dateNew = GMT+9 2013-01-01 12:10:10
mysql-〉 select dateInput, dateNew
结果不变: 2013-01-01 12:00:00 2013-01-01 12:10:10
------------- [color=blue] 读取数据到页面 [/color] -----------
[color=green]DB层[/color]
存储日期
数据库表中存储的dateInput和dateNew分别为
dateInput = 2013-01-01 12:00:00
dateNew = 2013-01-01 12:10:10
[color=green]BUSINESS 层[/color]
获取数据库存储日期,返回到页面
结果:
dateInput = GMT+8 2013-01-01 12:00:00
dateNew = GMT+8 2013-01-01 12:10:10
[color=green]VIEW 层[/color]
显示日期
<input value=<%=DateUtil.safeDateTime(map.get("dateInput"), locale, timeZone)%> />;
<input value=<%=dateFormatDateTime.format(dateNew)%> />;
<input value=<%=dateFormatDateTime.format(newDate())%> />;
页面显示结果
dateInput : 2013-01-01 11:00:00
dateNew : 2013-01-01 12:10:10
dateNew : 2013-01-01 12:10:10
------------- [color=blue] 总结 -----------
1. web app server 时区与 web server时区无关。
2. db server时区对程序无影响(不要使用now()函数更新数据库)
3. new date(), new dateformat() 生成对象时区为web app server 时区
4. 如果不考虑用户时区,则只需要设定tomcat时区即可保持系统一致。代码中适用new dateformat()格式化日期,部另外设置时区。
------------- [color=blue] END 2013-01-07 [/color] -----------
添加更新记录:用户输入本区域时间, 数据库存储转换后的标准时间
查看记录: 数据库时间相同,view层根据用户区域显示相应的时间
说明本项目要求日期格式固定,不按照用户local显示. 如果要求按照用户local显示日期格式则需要使用如下的format, 可参考liferay源码
Format dateFormat = FastDateFormatFactoryUtil.getSimpleDateFormat("MMMM, yyyy", locale);
dateFormat .setTimeZone(timeZone);
Format timeFormat = FastDateFormatFactoryUtil.getSimpleDateFormat("h:mma", locale);
timeFormat .setTimeZone(timeZone);
[color=blue]分析[/color]
liferay 提供了用户自定义zone (控制面板->setting->zone, 详见"liferay区域设置")。
页面显示时可以根据用户zone格式化取得的时间。
向后台发送数据时根据客户zone取得客户输入时间,转换为tomcat时间后再传入数据库
[color=red]原则(强烈建议[/color]
对于日期类型从后台向前台读取的过程中, 在business层不要做类型转换(例如试图转为long或String ), 只有在页面显示的时候才将其转为合适的日期格式和区域。
对于其他类型做同样的建议,如double, longtext,例如在business层中不要试图截取小数点位数和文本长度,在页面根据需要截取。如果业务上有特殊要求除外(如财务运算)
[color=blue]timezone 涉及的 web app 层次[/color]
1.view (jsp)
2.business(portletaction + service + finder/persistence)
//此处因为portlect负责读取输入的日期数据, finder负责写入日期数据,为方便说明timezone的传递,将其归入business层次, 勿纠结于层次划分
3.DB (mysql)
------------- [color=blue]util code[/color] -----------
DateUtil类提供公共方法获取包含用户时区和local的format
public class DateUtil {
public static SimpleDateFormat getDateFormatDate(Locale locale,
TimeZone timeZone) {
SimpleDateFormat dateFormatDate = new SimpleDateFormat("yyyy-MM-dd",
locale);
dateFormatDate.setTimeZone(timeZone);
return dateFormatDate;
}
public static SimpleDateFormat getDateFormatDateTime(Locale locale,
TimeZone timeZone) {
SimpleDateFormat dateFormatDate = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss", locale);
dateFormatDate.setTimeZone(timeZone);
return dateFormatDate;
}
public static String safeDate(Object obj, Locale locale, TimeZone timeZone) {
SimpleDateFormat dfCustomer = getDateFormatDate(locale, timeZone);
SimpleDateFormat dfServer = new SimpleDateFormat("yyyy-MM-dd");
String str = "";
try {
if (Validator.isNotNull(obj)) {
if (obj instanceof Date) {
str = dfCustomer.format(obj); //important
} else {
str = dfCustomer.format(dfServer.parse(obj.toString())); //important
}
}
} catch (Exception e) {
str = "";
}
return str;
}
public static String safeDateTime(Object obj, Locale locale,
TimeZone timeZone) {
SimpleDateFormat dfCustomer = getDateFormatDateTime(locale, timeZone);
SimpleDateFormat dfServer = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str = "";
try {
if (Validator.isNotNull(obj)) {
if (obj instanceof Date) {
str = dfCustomer.format(obj); //important
} else {
str = dfCustomer.format(dfServer.parse(obj.toString())); //important
}
}
} catch (Exception e) {
str = "";
}
return str;
}
}
html/init.jsp提供公共format,包含用户zone和local 也可以直接使用DateUtil类提供的方法
html/init.jsp
SimpleDateFormat dateFormatDate = DateUtil new SimpleDateFormat("yyyy-MM-dd", locale);
dateFormatDate.setTimeZone(timeZone);
SimpleDateFormat dateFormatDateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", locale);
dateFormatDateTime.setTimeZone(timeZone);
------------- [color=blue] zone设置 [/color] -----------
用户A,leferay中设置 zone = GMT+7
TOMCAT zone = GMT+8
mysql zone = system = GMT+9
设定
用户试图输入日期 GMT+8 2013-01-01 12:00:00 保存至数据库
执行操作时web server 系统时间 GMT+8 2013-01-01 12:10:10
// web server 系统时区可任意设置,不影响以下结果
------------- [color=blue] 添加更新记录 [/color] -----------
[color=green]VIEW 层[/color]
用户A输入日期 " 2013-01-01 11:00:00",提交 (GMT+7)
[color=green]BUSINESS 层[/color]
获取页面输入日期,更新数据库
//portlet:
ThemeDisplay themeDisplay = (ThemeDisplay)actionRequest.getAttribute( WebKeys.THEME_DISPLAY);
SimpleDateFormat dateFormatDateTime = DateUtil.getDateFormatDateTime(themeDisplay.getLocale(), themeDisplay.getTimeZone());
Date dateRead = ParamUtil.getDate(actionRequest, "date", dateFormatDateTime);
Date dateNew = new Date();
XXXLocalServiceUtil.XXX(xx, dateInput, dateNew);
/*
上面代码得到的日期为:
dateInput = GMT+8 2013-01-01 12:00:00
dateNew = GMT+8 2013-01-01 12:10:10
*/
//service:
ModelXXX modelxxx = ModelXXXPersistence.create(Id);
modelxxx.setdateInput(dateInput);
modelxxx.setdateNew(dateNew);
ModelXXXPersistence.update(modelxxx, false);
说明:
(1) dateFormatDateTime 的默认时区为用户时区GMT+7
(2) dateRead 获取时间为用户输入时间, 按照用户时区GMT+7转换为日期后再转换为tomcat时区GMT+8。
(3) new Date() 获取时间为 web server 系统时间, 时区为tomcat设置的时区GMT+8。
[color=red]注意:[/color]
ParamUtil.getDate(actionRequest, "date", dateFormatDateTime)方法实际隐含了两次转换
(1) 用户输入时间 2013-01-01 12:00:00,按用户时区(dateFormatDateTime) 转换为日期类型 GMT+7 2013-01-01 11:00:00
(2) GMT+7 2013-01-01 11:00:00 转换为tomcat时区 GMT+8 2013-01-01 12:00:00
[color=green]DB层[/color]
存储日期
数据库表中存储的dateInput和dateNew分别为
dateInput = 2013-01-01 12:00:00
dateNew = 2013-01-01 04:10:10
[color=red]注意:[/color]
数据库本身有时区定义,参见mysql时区定义。
mysql的时区定义会对now()获得字符串产生影响。
可以认为数据库存储的时间类型字段不包含时区信息,insert/update字符串即是所见字符串
例如:
传入参数:
dateInput = GMT+8 2013-01-01 12:00:00
dateNew = GMT+8 2013-01-01 12:10:10
mysql-〉 select dateInput, dateNew
结果: 2013-01-01 12:00:00 2013-01-01 12:10:10
传入参数:
dateInput = GMT+9 2013-01-01 12:00:00
dateNew = GMT+9 2013-01-01 12:10:10
mysql-〉 select dateInput, dateNew
结果不变: 2013-01-01 12:00:00 2013-01-01 12:10:10
------------- [color=blue] 读取数据到页面 [/color] -----------
[color=green]DB层[/color]
存储日期
数据库表中存储的dateInput和dateNew分别为
dateInput = 2013-01-01 12:00:00
dateNew = 2013-01-01 12:10:10
[color=green]BUSINESS 层[/color]
获取数据库存储日期,返回到页面
//finder:
map.put("dateInput", record[0] == null? "" : record[0]);
map.put("dateNew", record[1] == null? "" : record[1]);
/* 查询结果集
record[0] = Timestamp GMT+8 2013-01-01 12:00:00
record[1] = Timestamp GMT+8 2013-01-01 12:10:10
*/
//service:
Date dateInput = (Date)(map.get("dateInput"));
Date dateNew = (Date)(map.get("dateNew"));
/*
下面一种写法结果与上面代码相同, 但不提倡,finder和service中将Date和String来回转换存在风险SimpleDateFormat dateFormatDateTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date dateInput = dateFormatDateTime.parse(map.get("dateInput").toString());
Date dateNew = dateFormatDateTime.parse(map.get("dateNew").toString());
*/
结果:
dateInput = GMT+8 2013-01-01 12:00:00
dateNew = GMT+8 2013-01-01 12:10:10
[color=green]VIEW 层[/color]
显示日期
<input value=<%=DateUtil.safeDateTime(map.get("dateInput"), locale, timeZone)%> />;
<input value=<%=dateFormatDateTime.format(dateNew)%> />;
<input value=<%=dateFormatDateTime.format(newDate())%> />;
页面显示结果
dateInput : 2013-01-01 11:00:00
dateNew : 2013-01-01 12:10:10
dateNew : 2013-01-01 12:10:10
------------- [color=blue] 总结 -----------
1. web app server 时区与 web server时区无关。
2. db server时区对程序无影响(不要使用now()函数更新数据库)
3. new date(), new dateformat() 生成对象时区为web app server 时区
4. 如果不考虑用户时区,则只需要设定tomcat时区即可保持系统一致。代码中适用new dateformat()格式化日期,部另外设置时区。
------------- [color=blue] END 2013-01-07 [/color] -----------