Skip to main content

9D4.Auto Timezone and I18n

trydoforOriginalPracticeManualAbout 2 min

9D4.Auto Timezone and I18n

The careful handling of language and timezones is an important feature that distinguishes WingsBoot from other frameworks.

  • time - can system-level, thread-level tweak clock
  • timezone - by annotation or type , to auto convert Dto/pojo
  • language - strong type MessageCode, EnumCode constants with auto conversion

Tweak Clock and Timeline

There are typically two types of clocks within a system, the system clock, which requires a linear timeline, and the business clock, which may require traversal. The system clock may also need to be tuned to a different timeline, especially during test, deduce and replay.

  • mirana's ThreadNow and SlideDate basic version to tweak system clock
  • slardar's Now advanced version to tweak system clock, also the user timeline

So, when writing a program, if you need to tweak the timeline (all business code is recommended)

  • Now.xxx() instead of Xxxx.now() if dep on slardar
  • ThreadNow.xxx() instead, if not dep on slardar, but on mirana dependency

It is important to note whether the business thread model supports ThreadLocal's Inheritable.

  • ThreadNow use ThreadLocal by default
  • Now uses TransmittableThreadLocal by default to override the default value of ThreadNow

The jmh Benchmark on ThreadNow.xxx() and Xxx.now() is basically the same

Benchmark     Mode  Cnt      Score     Error   Units
NowMain.now  thrpt    6  11942.923 ± 368.430  ops/ms
NowMain.sys  thrpt    6  12910.824 ± 226.997  ops/ms

I18n of Time and Text

WingsBoot's automatic conversion relies on two Contexts to get the ZoneId and Locale

  • spring's LocaleContextHolder, used in the web layer
  • slardar's TerminalContext, which is recommended, especially in the Service layer

Automatic conversion occurs in SpringMvc's Request and Response, respectively

  • Jackson's @RequestBody, @ResponseBody
  • Spring's Data Binding, such as @Param

Manual conversions are handled by AutoDtoHelper, such as Excel output, but avoid automatic conversions.

  • Only works for annotation fields by default, while auto-conversion can be handled by type
  • Only non-final and transient fields with getters are supported by default

The types and configuration items involved in auto-conversion are

  • LocaleDateTime - wings.slardar.datetime.datetime.auto=false
  • ZonedDateTime - wings.slardar.datetime.zoned.auto=false
  • OffsetDateTime - wings.slardar.datetime.offset.auto=true
  • I18nString - without config, auto convert

The annotations involved in the automatic and manual conversions are

  • AutoDtoAble - marks the container class field (manual conversion only)
  • AutoI18nString - marks String or I18nString type
  • AutoTimeZone - marks the DateTime of Local/Zoned/Offset

Context Rule and Pitfall

All Context implicitly passing variables, that have side effects, are considered anti-patterns and should follow the rules and be used with caution. Avoid using Functions with sideEffects in Wings, but Context does provide convenience and works very well.

ThreadLocal is often used to implement Context, and ThreadLocal must be set and removed correctly. Either in try{set}finally{remove} or some mechanism to ensure there are no misreads or memory leaks.

Wings uses Transmittable-ThreadLocalopen in new window by default, and use TransmittableThreadLocal whenever possible, wrap Spring's Executor as TtlExecutors to ensure correct Context passing.

In scenarios with complex thread models, be sure to follow the principles and concerns of Transmittable-ThreadLocal to correctly handle the Context and ensure proper business code.

  • TerminalContext - handled by slardar's TerminalInterceptor
  • Now - As business requirement, need to try{adjust()}finally{remove()} by yourself