DateTimeFormat.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (c) 2021-2022, Tim Flynn <trflynn89@pm.me>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Array.h>
  7. #include <AK/StringBuilder.h>
  8. #include <LibUnicode/DateTimeFormat.h>
  9. #include <LibUnicode/Locale.h>
  10. namespace Unicode {
  11. HourCycle hour_cycle_from_string(StringView hour_cycle)
  12. {
  13. if (hour_cycle == "h11"sv)
  14. return Unicode::HourCycle::H11;
  15. else if (hour_cycle == "h12"sv)
  16. return Unicode::HourCycle::H12;
  17. else if (hour_cycle == "h23"sv)
  18. return Unicode::HourCycle::H23;
  19. else if (hour_cycle == "h24"sv)
  20. return Unicode::HourCycle::H24;
  21. VERIFY_NOT_REACHED();
  22. }
  23. StringView hour_cycle_to_string(HourCycle hour_cycle)
  24. {
  25. switch (hour_cycle) {
  26. case HourCycle::H11:
  27. return "h11"sv;
  28. case HourCycle::H12:
  29. return "h12"sv;
  30. case HourCycle::H23:
  31. return "h23"sv;
  32. case HourCycle::H24:
  33. return "h24"sv;
  34. default:
  35. VERIFY_NOT_REACHED();
  36. }
  37. }
  38. CalendarPatternStyle calendar_pattern_style_from_string(StringView style)
  39. {
  40. if (style == "narrow"sv)
  41. return CalendarPatternStyle::Narrow;
  42. if (style == "short"sv)
  43. return CalendarPatternStyle::Short;
  44. if (style == "long"sv)
  45. return CalendarPatternStyle::Long;
  46. if (style == "numeric"sv)
  47. return CalendarPatternStyle::Numeric;
  48. if (style == "2-digit"sv)
  49. return CalendarPatternStyle::TwoDigit;
  50. if (style == "shortOffset"sv)
  51. return CalendarPatternStyle::ShortOffset;
  52. if (style == "longOffset"sv)
  53. return CalendarPatternStyle::LongOffset;
  54. if (style == "shortGeneric"sv)
  55. return CalendarPatternStyle::ShortGeneric;
  56. if (style == "longGeneric"sv)
  57. return CalendarPatternStyle::LongGeneric;
  58. VERIFY_NOT_REACHED();
  59. }
  60. StringView calendar_pattern_style_to_string(CalendarPatternStyle style)
  61. {
  62. switch (style) {
  63. case CalendarPatternStyle::Narrow:
  64. return "narrow"sv;
  65. case CalendarPatternStyle::Short:
  66. return "short"sv;
  67. case CalendarPatternStyle::Long:
  68. return "long"sv;
  69. case CalendarPatternStyle::Numeric:
  70. return "numeric"sv;
  71. case CalendarPatternStyle::TwoDigit:
  72. return "2-digit"sv;
  73. case CalendarPatternStyle::ShortOffset:
  74. return "shortOffset"sv;
  75. case CalendarPatternStyle::LongOffset:
  76. return "longOffset"sv;
  77. case CalendarPatternStyle::ShortGeneric:
  78. return "shortGeneric"sv;
  79. case CalendarPatternStyle::LongGeneric:
  80. return "longGeneric"sv;
  81. default:
  82. VERIFY_NOT_REACHED();
  83. }
  84. }
  85. Optional<Calendar> __attribute__((weak)) calendar_from_string(StringView) { return {}; }
  86. Optional<HourCycleRegion> __attribute__((weak)) hour_cycle_region_from_string(StringView) { return {}; }
  87. Vector<HourCycle> __attribute__((weak)) get_regional_hour_cycles(StringView) { return {}; }
  88. // https://unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
  89. Vector<Unicode::HourCycle> get_locale_hour_cycles(StringView locale)
  90. {
  91. if (auto hour_cycles = get_regional_hour_cycles(locale); !hour_cycles.is_empty())
  92. return hour_cycles;
  93. auto return_default_hour_cycles = [&]() { return get_regional_hour_cycles("001"sv); };
  94. auto language = parse_unicode_language_id(locale);
  95. if (!language.has_value())
  96. return return_default_hour_cycles();
  97. if (!language->region.has_value())
  98. language = add_likely_subtags(*language);
  99. if (!language.has_value() || !language->region.has_value())
  100. return return_default_hour_cycles();
  101. if (auto hour_cycles = get_regional_hour_cycles(*language->region); !hour_cycles.is_empty())
  102. return hour_cycles;
  103. return return_default_hour_cycles();
  104. }
  105. Optional<Unicode::HourCycle> get_default_regional_hour_cycle(StringView locale)
  106. {
  107. if (auto hour_cycles = get_locale_hour_cycles(locale); !hour_cycles.is_empty())
  108. return hour_cycles.first();
  109. return {};
  110. }
  111. String combine_skeletons(StringView first, StringView second)
  112. {
  113. // https://unicode.org/reports/tr35/tr35-dates.html#availableFormats_appendItems
  114. constexpr auto field_order = Array {
  115. "G"sv, // Era
  116. "yYuUr"sv, // Year
  117. "ML"sv, // Month
  118. "dDFg"sv, // Day
  119. "Eec"sv, // Weekday
  120. "abB"sv, // Period
  121. "hHKk"sv, // Hour
  122. "m"sv, // Minute
  123. "sSA"sv, // Second
  124. "zZOvVXx"sv, // Zone
  125. };
  126. StringBuilder builder;
  127. auto append_from_skeleton = [&](auto skeleton, auto ch) {
  128. auto first_index = skeleton.find(ch);
  129. if (!first_index.has_value())
  130. return false;
  131. auto last_index = skeleton.find_last(ch);
  132. builder.append(skeleton.substring_view(*first_index, *last_index - *first_index + 1));
  133. return true;
  134. };
  135. for (auto fields : field_order) {
  136. for (auto ch : fields) {
  137. if (append_from_skeleton(first, ch))
  138. break;
  139. if (append_from_skeleton(second, ch))
  140. break;
  141. }
  142. }
  143. return builder.build();
  144. }
  145. Optional<CalendarFormat> __attribute__((weak)) get_calendar_date_format(StringView, StringView) { return {}; }
  146. Optional<CalendarFormat> __attribute__((weak)) get_calendar_time_format(StringView, StringView) { return {}; }
  147. Optional<CalendarFormat> __attribute__((weak)) get_calendar_date_time_format(StringView, StringView) { return {}; }
  148. Optional<CalendarFormat> get_calendar_format(StringView locale, StringView calendar, CalendarFormatType type)
  149. {
  150. switch (type) {
  151. case CalendarFormatType::Date:
  152. return get_calendar_date_format(locale, calendar);
  153. case CalendarFormatType::Time:
  154. return get_calendar_time_format(locale, calendar);
  155. case CalendarFormatType::DateTime:
  156. return get_calendar_date_time_format(locale, calendar);
  157. default:
  158. VERIFY_NOT_REACHED();
  159. }
  160. }
  161. Vector<CalendarPattern> __attribute__((weak)) get_calendar_available_formats(StringView, StringView) { return {}; }
  162. Optional<CalendarRangePattern> __attribute__((weak)) get_calendar_default_range_format(StringView, StringView) { return {}; }
  163. Vector<CalendarRangePattern> __attribute__((weak)) get_calendar_range_formats(StringView, StringView, StringView) { return {}; }
  164. Vector<CalendarRangePattern> __attribute__((weak)) get_calendar_range12_formats(StringView, StringView, StringView) { return {}; }
  165. Optional<StringView> __attribute__((weak)) get_calendar_era_symbol(StringView, StringView, CalendarPatternStyle, Era) { return {}; }
  166. Optional<StringView> __attribute__((weak)) get_calendar_month_symbol(StringView, StringView, CalendarPatternStyle, Month) { return {}; }
  167. Optional<StringView> __attribute__((weak)) get_calendar_weekday_symbol(StringView, StringView, CalendarPatternStyle, Weekday) { return {}; }
  168. Optional<StringView> __attribute__((weak)) get_calendar_day_period_symbol(StringView, StringView, CalendarPatternStyle, DayPeriod) { return {}; }
  169. Optional<StringView> __attribute__((weak)) get_calendar_day_period_symbol_for_hour(StringView, StringView, CalendarPatternStyle, u8) { return {}; }
  170. Optional<StringView> __attribute__((weak)) get_time_zone_name(StringView, StringView, CalendarPatternStyle) { return {}; }
  171. }