`
likaidalian
  • 浏览: 53973 次
社区版块
存档分类
最新评论

web app timezone (view-business-db)

阅读更多
目标:面向多区域用户
添加更新记录:用户输入本区域时间, 数据库存储转换后的标准时间
查看记录: 数据库时间相同,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);


分析
liferay 提供了用户自定义zone (控制面板->setting->zone, 详见"liferay区域设置")。
页面显示时可以根据用户zone格式化取得的时间。
向后台发送数据时根据客户zone取得客户输入时间,转换为tomcat时间后再传入数据库

原则(强烈建议
对于日期类型从后台向前台读取的过程中, 在business层不要做类型转换(例如试图转为long或String ), 只有在页面显示的时候才将其转为合适的日期格式和区域。
对于其他类型做同样的建议,如double, longtext,例如在business层中不要试图截取小数点位数和文本长度,在页面根据需要截取。如果业务上有特殊要求除外(如财务运算)

timezone 涉及的 web app 层次
1.view (jsp)
2.business(portletaction + service + finder/persistence)
  //此处因为portlect负责读取输入的日期数据, finder负责写入日期数据,为方便说明timezone的传递,将其归入business层次, 勿纠结于层次划分
3.DB (mysql)

------------- util code   -----------
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);


------------- zone设置      -----------
用户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 系统时区可任意设置,不影响以下结果

------------- 添加更新记录      -----------
VIEW 层
用户A输入日期 " 2013-01-01 11:00:00",提交 (GMT+7)

BUSINESS 层
获取页面输入日期,更新数据库

//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。

注意:
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

DB层
存储日期

数据库表中存储的dateInput和dateNew分别为
dateInput =  2013-01-01 12:00:00
dateNew =  2013-01-01 04:10:10

注意:
数据库本身有时区定义,参见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

------------- 读取数据到页面    -----------

DB层
存储日期

数据库表中存储的dateInput和dateNew分别为
dateInput =  2013-01-01 12:00:00
dateNew =   2013-01-01 12:10:10


BUSINESS 层

获取数据库存储日期,返回到页面
//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

VIEW 层
显示日期
<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

------------- 总结 -----------
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
-----------
分享到:
评论

相关推荐

    appweb-5.1.0-src.tgz

    **AppWeb服务器详解** AppWeb是一款轻量级、高性能的嵌入式Web服务器,它以其高效、可扩展和安全的特性在IT行业中受到广泛关注。"appweb-5.1.0-src.tgz" 是AppWeb的5.1.0版本源代码包,这代表着开发者可以获取到...

    uni-app app实现web-view H5图片长按下载

    在uni-app框架中,开发移动应用时经常需要集成H5页面,通过`&lt;web-view&gt;`组件展示。然而,原生的H5图片长按下载功能在uni-app内可能无法正常工作,因为平台的限制或者API的不兼容。在这种情况下,我们需要自定义处理...

    appweb-src-3.2.3-3.tar.gz

    《AppWeb源码分析与应用》 AppWeb是一款开源的嵌入式Web服务器,它以其轻量级、高效能的特点,被广泛应用于各种嵌入式设备和物联网系统中。本篇将围绕“appweb-src-3.2.3-3.tar.gz”这个压缩包中的源代码,深入探讨...

    angulr-bootstrap-admin-web-app-with-angularjs-2.x版本

    angulr-bootstrap-admin-web-app-with-angularjs 2.0版本来拉。由于最近比较忙所有没有持续更新这个版本。在此特地发一下2.0.1版本的。如果有需要我之前版本的请查看我的资源,移驾之前的资源。绝对官网下载的完整包...

    appweb-src-2.4.0-0.tar.gz_嵌入式web

    `appweb-src-2.4.0-0.tar.gz`是一个强大的嵌入式Web服务器解决方案,它为资源有限的设备带来了丰富的Web服务功能,包括动态脚本支持和高度的可定制性。开发者可以通过其源代码包进行编译、安装,并根据需求进行配置...

    appweb-src-3.2.2-1.tar.gz

    《AppWeb 3.2.2-1 源码解析与应用开发指南》 AppWeb,一个轻量级、高性能的嵌入式Web服务器,以其开源、小巧且功能强大的特性,深受开发者们的喜爱。本篇文章将围绕"appweb-src-3.2.2-1.tar.gz"这一版本的源码进行...

    前端开源库-web-app-manifest-loader

    "web-app-manifest-loader" 是一个专门针对Web应用程序清单(Web App Manifest)处理的前端开源库。本文将深入探讨这个库的核心功能、用途以及它如何融入Web开发流程。 Web应用程序清单(Web App Manifest)是一种...

    appweb-src-2.4.3-0.tar.gz_Linux服務器_appweb_appweb-src-_嵌入式 安全_嵌入式

    Appweb是一個嵌入式HTTP Web服務器,主要的設計思路是安全。這是直接集成到客戶的應用和設備,便於開發和部署基於Web的應用程序和設備。它正迅速( 3500多要求每秒)和緊湊(從11萬) ,其中包括支持動態網頁製作,...

    webpack-web-app-manifest-plugin:一个Webpack插件,可生成PWA清单并与资产JSON集成

    webpack-web-app-manifest-plugin webpack-web-app-manifest-plugin是一个Webpack插件,可生成PWA清单并与生成的资产JSON集成。如何安装npm install --save-dev webpack-web-app-manifest-plugin 或者yarn add ...

    Web-App-Developer-2-by-InfoQ

    Web-App-Developer-2-by-InfoQ

    appweb-2.4.2-2M-src

    **AppWeb 2.4.2-2M-src 源码详解** AppWeb 是一款轻量级、高效的嵌入式 Web 服务器,其源码包 "appweb-2.4.2-2M-src" 提供了在各种平台,包括 ARM 和 PC 上搭建和移植的完整解决方案。这款 Web 服务器以其小巧的...

    appweb-3.3.2-0-src

    标题“appweb-3.3.2-0-src”揭示了我们要讨论的核心——appweb服务器的一个特定版本,即3.3.2。这是一个开源的、轻量级的Web服务器,专为嵌入式系统设计,适用于各种资源有限的环境。"src"后缀表明我们获得的是源...

    关于uni-app使用web-view页面之间互相跳转、通信等问题的解决方案.docx

    &lt;title&gt;uni-app-web-view &lt;!-- 引入uni-app SDK --&gt; &lt;script type="text/javascript" src="https://js.cdn.aliyun.dcloud.net.cn/dev/uni-app/uni.webview.0.1.52.js"&gt; document.addEventListener('...

    appweb-6.2.1-src.tgz

    **AppWeb 6.2.1 源代码详解** AppWeb 是一款开源的嵌入式 Web 服务器,它设计轻量级、高效且可高度定制。标题中的 "appweb-6.2.1-src.tgz" 表明这是一个 AppWeb 的 6.2.1 版本的源代码压缩包,格式为 tar.gz,通常...

    appweb-src-2.4.2-2M.tar.gz_SRC_appweb_goahead_web server_web服务器

    AppWeb是完全遵循GPL软件许可协议(GNU General Public License)的开源Web服务器。 AppWeb Web服务器软件在功能上比GoAhead更加丰富和实用, 除了GoAhead已有的功能之外,还有如下特点: 支持服务器端的...

    appweb4.3.4-0添加arm配置及源代码

    2. **主循环**:在`src/appweb.c`中,你可以找到服务器的主要事件循环,这是AppWeb运行的核心部分。 3. **配置解析**:AppWeb使用`conf.c`和`conf.h`中的函数来解析配置文件。了解这些函数的工作原理,可以方便地...

    Office Web App Server 2013

    Add-WindowsFeature Web-Server,Web-WebServer,Web-Common-Http,Web-Static-Content,Web-App-Dev,Web-Asp-Net,Web-Net-Ext,Web-ISAPI-Ext,Web-ISAPI-Filter,Web-Includes,Web-Security,Web-Windows-Auth,Web-...

    Office web app server2013安装与部署

    Add-WindowsFeature Web-Server, Web-WebServer, Web-Common-Http, Web-Static-Content, Web-App-Dev, Web-Asp-Net, Web-Net-Ext, Web-ISAPI-Ext, Web-ISAPI-Filter, Web-Includes, Web-Security, Web-Windows-Auth...

    WhatsApp-Business-API-Setup-Scripts:与设置WhatsApp业务API相关的脚本

    WhatsApp业务API设置脚本(英语) 该存储库包含用于使用docker-compose设置WhatsApp Business API的所有配置脚本。 有关与WhatsApp Business API有关的更多详细信息,请访问以下位置的文档: : 执照WhatsApp业务API...

    mall-app-web是一个电商系统的移动端项目,基于uni-app实现。

    mall-app-web是一个电商系统的移动端项目,基于uni-app实现。主要包括首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等功能。.zip 适合学习/练手、毕业设计、课程设计、...

Global site tag (gtag.js) - Google Analytics