使用Spring MVC + Freemarker处理用户特定日期/时区转换的最佳方法

Pat*_*ier 5 java spring freemarker date spring-mvc

我想显示使用用户时区格式化的存储日期(时区为UTC)(可能因用户而异,并存储在配置文件中).

我提出的解决方案是以下一个,我想知道这是否是最好的方法,或者是否有另一个,可能更简单的解决方案.

时区设置为UTC:

-Duser.timezone=UTC
Run Code Online (Sandbox Code Playgroud)

控制器,Freemarker-Template,HandlerInterceptor:

控制器:

@Controller
@RequestMapping("/test")
public class TestController {

        @RequestMapping
        public String dateTest(Model model){
                final Date date = new Date();
                model.addAttribute("formattedDate", new SimpleDateFormat("hh:mm:ss").format(date));
                model.addAttribute("date", date);              
                return "test";
        }
}
Run Code Online (Sandbox Code Playgroud)

Freemarker的,模板:

<#setting time_zone="${currentTimeZone}">

UTC Time: ${formattedDate}<br/>
Localized time for timezone <i>${currentTimeZone}</i>: ${date?time}
Run Code Online (Sandbox Code Playgroud)

HandlerInterceptor接口:

public class TimezoneHandlerInterceptor extends HandlerInterceptorAdapter{

        @Override
        public void postHandle(HttpServletRequest request,
                        HttpServletResponse response, Object handler,
                        ModelAndView modelAndView) throws Exception {

                //Only for testing, in production something like: 
                //final String currentUserTimezone = userService.getCurrentUser().getTimezoneId();
                final String currentUserTimezone = "Europe/Berlin";

                modelAndView.addObject("currentTimeZone", currentUserTimezone);            
        }
}
Run Code Online (Sandbox Code Playgroud)

输出:

UTC Time: 08:03:53
Localized time for timezone Europe/Berlin: 09:03:53
Run Code Online (Sandbox Code Playgroud)

那么是否有更标准或甚至开箱即用的方法来实现相同的结果?谢谢你的帮助.

dde*_*any 3

由于您打印相同的日期两次,仅以不同的方式呈现(不同的时区),因此它可能只是演示(MVC 视图)问题,因此不应在模型中解决。相反,您可以在模板中执行如下操作:

<#import "/lib/utils.ftl" as u>
...
UTC Time: ${u.utcTime(date)}<br/>
Localized time for timezone <i>${currentTimeZone}</i>: ${date?time}
Run Code Online (Sandbox Code Playgroud)

utcTime应该在utils.ftllike内部定义<#assign u = "com.something.freemarker.UtcTimeMethod"?new()>,其中com.something.freemarker.UtcTimeMethod是一个TemplateMethodModelEx实现。还有其他方法可以做到这一点,比如u可能是在 FreeMarker 配置中定义的共享变量等。重点是,您需要打印 UTC 时间不会影响模型。

至于这<#setting time_zone=currentTimeZone>部分(请注意,没有必要${...}),它当然取决于 Web 应用程序框架,但最好的解决方案是在调用模板之前设置时区(例如基于访问者的区域设置)。FreeMarker 通过Template.createProcessingEnvironment(参见 JavaDoc)支持这一点,但 Spring MVC 可能不支持。

此外,Date对象始终以 UTC 格式存储日期时间。您无需使用 来设置时区-D