You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LocaleUtil.java 5.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* ====================================================================
  2. Licensed to the Apache Software Foundation (ASF) under one or more
  3. contributor license agreements. See the NOTICE file distributed with
  4. this work for additional information regarding copyright ownership.
  5. The ASF licenses this file to You under the Apache License, Version 2.0
  6. (the "License"); you may not use this file except in compliance with
  7. the License. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.util;
  16. import java.nio.charset.Charset;
  17. import java.time.ZoneOffset;
  18. import java.util.Calendar;
  19. import java.util.Locale;
  20. import java.util.TimeZone;
  21. /**
  22. * This utility class is used to set locale and time zone settings beside
  23. * of the JDK internal {@link java.util.Locale#setDefault(Locale)} and
  24. * {@link java.util.TimeZone#setDefault(TimeZone)} methods, because
  25. * the locale/time zone specific handling of certain office documents -
  26. * maybe for different time zones / locales ... - shouldn't affect
  27. * other java components.
  28. *
  29. * The settings are saved in a {@link java.lang.ThreadLocal},
  30. * so they only apply to the current thread and can't be set globally.
  31. */
  32. public final class LocaleUtil {
  33. private LocaleUtil() {
  34. // no instances of this class
  35. }
  36. /**
  37. * Excel doesn't store TimeZone information in the file, so if in doubt,
  38. * use UTC to perform calculations
  39. */
  40. public static final TimeZone TIMEZONE_UTC = TimeZone.getTimeZone(ZoneOffset.UTC);
  41. /**
  42. * Default encoding for unknown byte encodings of native files
  43. * (at least it's better than to rely on a platform dependent encoding
  44. * for legacy stuff ...)
  45. */
  46. public static final Charset CHARSET_1252 = Charset.forName("CP1252");
  47. private static final ThreadLocal<TimeZone> userTimeZone = new ThreadLocal<>();
  48. private static final ThreadLocal<Locale> userLocale = new ThreadLocal<>();
  49. static {
  50. // allow to clear all thread-locals via ThreadLocalUtil
  51. ThreadLocalUtil.registerCleaner(() -> {
  52. userTimeZone.remove();
  53. userLocale.remove();
  54. });
  55. }
  56. /**
  57. * As time zone information is not stored in any format, it can be
  58. * set before any date calculations take place.
  59. * This setting is specific to the current thread.
  60. *
  61. * @param timezone the timezone under which date calculations take place
  62. */
  63. public static void setUserTimeZone(TimeZone timezone) {
  64. userTimeZone.set(timezone);
  65. }
  66. /**
  67. * @return the time zone which is used for date calculations. If not set, returns {@link TimeZone#getDefault()}.
  68. */
  69. @SuppressForbidden("implementation around default locales in POI")
  70. public static TimeZone getUserTimeZone() {
  71. TimeZone timeZone = userTimeZone.get();
  72. return (timeZone != null) ? timeZone : TimeZone.getDefault();
  73. }
  74. /**
  75. * Clear the thread-local user time zone.
  76. */
  77. public static void resetUserTimeZone() {
  78. userTimeZone.remove();
  79. }
  80. /**
  81. * Sets default user locale.
  82. * This setting is specific to the current thread.
  83. */
  84. public static void setUserLocale(Locale locale) {
  85. userLocale.set(locale);
  86. }
  87. /**
  88. * @return the default user locale. If not set, returns {@link Locale#getDefault()}.
  89. */
  90. @SuppressForbidden("implementation around default locales in POI")
  91. public static Locale getUserLocale() {
  92. Locale locale = userLocale.get();
  93. return (locale != null) ? locale : Locale.getDefault();
  94. }
  95. public static void resetUserLocale() {
  96. userLocale.remove();
  97. }
  98. /**
  99. * @return a calendar for the user locale and time zone
  100. */
  101. public static Calendar getLocaleCalendar() {
  102. return getLocaleCalendar(getUserTimeZone());
  103. }
  104. /**
  105. * Convenience method - month is 0-based as in java.util.Calendar
  106. *
  107. * @return a calendar for the user locale and time zone, and the given date
  108. */
  109. public static Calendar getLocaleCalendar(int year, int month, int day) {
  110. return getLocaleCalendar(year, month, day, 0, 0, 0);
  111. }
  112. /**
  113. * Convenience method - month is 0-based as in java.util.Calendar
  114. *
  115. * @return a calendar for the user locale and time zone, and the given date
  116. */
  117. public static Calendar getLocaleCalendar(int year, int month, int day, int hour, int minute, int second) {
  118. Calendar cal = getLocaleCalendar();
  119. cal.set(year, month, day, hour, minute, second);
  120. cal.clear(Calendar.MILLISECOND);
  121. return cal;
  122. }
  123. /**
  124. * @return a calendar for the user locale and time zone
  125. */
  126. public static Calendar getLocaleCalendar(TimeZone timeZone) {
  127. return Calendar.getInstance(timeZone, getUserLocale());
  128. }
  129. /**
  130. * Decode the language ID from LCID value
  131. *
  132. * @param lcid the LCID value
  133. * @return the locale/language ID
  134. */
  135. public static String getLocaleFromLCID(int lcid) {
  136. LocaleID lid = LocaleID.lookupByLcid(lcid & 0xFFFF);
  137. return (lid == null) ? "invalid" : lid.getLanguageTag();
  138. }
  139. /**
  140. * Get default code page from LCID value
  141. *
  142. * @param lcid the LCID value
  143. * @return the default code page
  144. */
  145. public static int getDefaultCodePageFromLCID(int lcid) {
  146. LocaleID lid = LocaleID.lookupByLcid(lcid & 0xFFFF);
  147. return (lid == null) ? 0 : lid.getDefaultCodepage();
  148. }
  149. }