llvm-project/libcxx/test/std/time/time.syn/formatter.gps_time.pass.cpp
Mark de Wever cf50936b23
[libc++][chrono] implements GPS clock. (#125921)
Completes:
- LWG3359 <chrono> leap second support should allow for negative leap
seconds
- P1361R2 Integration of chrono with text formatting

Implements parts of:
- P0355 Extending <chrono> to Calendars and Time Zones

Fixes: #100432
Fixes: #100014
2025-02-21 17:50:01 +01:00

991 lines
36 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//===----------------------------------------------------------------------===//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// REQUIRES: std-at-least-c++20
// UNSUPPORTED: no-filesystem, no-localization, no-tzdb
// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
// TODO FMT This test should not require std::to_chars(floating-point)
// XFAIL: availability-fp_to_chars-missing
// XFAIL: libcpp-has-no-experimental-tzdb
// XFAIL: availability-tzdb-missing
// REQUIRES: locale.fr_FR.UTF-8
// REQUIRES: locale.ja_JP.UTF-8
// <chrono>
// template<class Duration, class charT>
// struct formatter<chrono::gps_time<Duration>, charT>;
#include <chrono>
#include <format>
#include <cassert>
#include <concepts>
#include <locale>
#include <iostream>
#include <type_traits>
#include "formatter_tests.h"
#include "make_string.h"
#include "platform_support.h" // locale name macros
#include "test_macros.h"
template <class CharT>
static void test_no_chrono_specs() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output
// [time.syn]
// using nanoseconds = duration<signed integer type of at least 64 bits, nano>;
// using microseconds = duration<signed integer type of at least 55 bits, micro>;
// using milliseconds = duration<signed integer type of at least 45 bits, milli>;
// using seconds = duration<signed integer type of at least 35 bits>;
// using minutes = duration<signed integer type of at least 29 bits, ratio< 60>>;
// using hours = duration<signed integer type of at least 23 bits, ratio<3600>>;
check(SV("1435-08-09 22:07:05"), SV("{}"), cr::gps_seconds(-17'179'869'184s)); // Minimum value for 35 bits.
check(SV("1911-12-18 20:46:01"), SV("{}"), cr::gps_seconds(-2'147'483'648s));
check(SV("1980-01-05 00:00:00"), SV("{}"), cr::gps_seconds(-24h));
check(SV("1980-01-05 06:00:00"), SV("{}"), cr::gps_seconds(-18h));
check(SV("1980-01-05 12:00:00"), SV("{}"), cr::gps_seconds(-12h));
check(SV("1980-01-05 18:00:00"), SV("{}"), cr::gps_seconds(-6h));
check(SV("1980-01-05 23:59:59"), SV("{}"), cr::gps_seconds(-1s));
check(SV("1980-01-06 00:00:00"), SV("{}"), cr::gps_seconds(0s));
check(SV("2010-01-04 23:59:45"), SV("{}"), cr::gps_seconds(946'684'800s));
check(SV("2010-01-05 01:01:48"), SV("{}"), cr::gps_seconds(946'688'523s));
check(SV("2048-01-24 03:13:49"), SV("{}"), cr::gps_seconds(2'147'483'647s));
check(SV("2524-06-03 01:52:45"), SV("{}"), cr::gps_seconds(17'179'869'183s)); // Maximum value for 35 bits.
check(SV("2010-01-05 01:01:48.123"), SV("{}"), cr::gps_time<cr::milliseconds>(946'688'523'123ms));
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values_year() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
constexpr std::basic_string_view<CharT> fmt =
SV("{:%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");
constexpr std::basic_string_view<CharT> lfmt =
SV("{:L%%C='%C'%t%%EC='%EC'%t%%y='%y'%t%%Oy='%Oy'%t%%Ey='%Ey'%t%%Y='%Y'%t%%EY='%EY'%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%C='19'\t%EC='19'\t%y='80'\t%Oy='80'\t%Ey='80'\t%Y='1980'\t%EY='1980'\n"),
fmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
fmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
// Use the global locale (fr_FR)
check(SV("%C='19'\t%EC='19'\t%y='80'\t%Oy='80'\t%Ey='80'\t%Y='1980'\t%EY='1980'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
// Use supplied locale (ja_JP). This locale has a different alternate.
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
check(loc,
SV("%C='19'\t%EC='19'\t%y='80'\t%Oy='80'\t%Ey='80'\t%Y='1980'\t%EY='1980'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%C='20'\t%EC='20'\t%y='09'\t%Oy='09'\t%Ey='09'\t%Y='2009'\t%EY='2009'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)||defined(__FreeBSD__)
check(loc,
SV("%C='19'\t%EC='昭和'\t%y='80'\t%Oy='八十'\t%Ey='55'\t%Y='1980'\t%EY='昭和55年'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%C='20'\t%EC='平成'\t%y='09'\t%Oy='九'\t%Ey='21'\t%Y='2009'\t%EY='平成21年'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX)||defined(__FreeBSD__)
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values_month() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
constexpr std::basic_string_view<CharT> fmt = SV("{:%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%b='%b'%t%%h='%h'%t%%B='%B'%t%%m='%m'%t%%Om='%Om'%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%b='Jan'\t%h='Jan'\t%B='January'\t%m='01'\t%Om='01'\n"),
fmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%b='May'\t%h='May'\t%B='May'\t%m='05'\t%Om='05'\n"),
fmt,
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS on Wednesday, 18 May 2033
// Use the global locale (fr_FR)
#if defined(__APPLE__)
check(SV("%b='jan'\t%h='jan'\t%B='janvier'\t%m='01'\t%Om='01'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
#else
check(SV("%b='janv.'\t%h='janv.'\t%B='janvier'\t%m='01'\t%Om='01'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
#endif
check(SV("%b='mai'\t%h='mai'\t%B='mai'\t%m='05'\t%Om='05'\n"),
lfmt,
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS on Wednesday, 18 May 2033
// Use supplied locale (ja_JP). This locale has a different alternate.
#ifdef _WIN32
check(loc,
SV("%b='1'\t%h='1'\t%B='1月'\t%m='01'\t%Om='01'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%b='5'\t%h='5'\t%B='5月'\t%m='05'\t%Om='05'\n"),
lfmt,
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
#elif defined(_AIX) // _WIN32
check(loc,
SV("%b='1月'\t%h='1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%b='5月'\t%h='5月'\t%B='5月'\t%m='05'\t%Om='05'\n"),
lfmt,
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
#elif defined(__APPLE__) // _WIN32
check(loc,
SV("%b=' 1'\t%h=' 1'\t%B='1月'\t%m='01'\t%Om='01'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%b=' 5'\t%h=' 5'\t%B='5月'\t%m='05'\t%Om='05'\n"),
lfmt,
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
#elif defined(__FreeBSD__) // _WIN32
check(loc,
SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='01'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%b=' 5月'\t%h=' 5月'\t%B='5月'\t%m='05'\t%Om='05'\n"),
lfmt,
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
#else // _WIN32
check(loc,
SV("%b=' 1月'\t%h=' 1月'\t%B='1月'\t%m='01'\t%Om='一'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%b=' 5月'\t%h=' 5月'\t%B='5月'\t%m='05'\t%Om='五'\n"),
lfmt,
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
#endif // _WIN32
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values_day() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
constexpr std::basic_string_view<CharT> fmt = SV("{:%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%d='%d'%t%%Od='%Od'%t%%e='%e'%t%%Oe='%Oe'%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%d='06'\t%Od='06'\t%e=' 6'\t%Oe=' 6'\n"), fmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
fmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
// Use the global locale (fr_FR)
check(SV("%d='06'\t%Od='06'\t%e=' 6'\t%Oe=' 6'\n"), lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
// Use the global locale (fr_FR)
check(SV("%d='06'\t%Od='06'\t%e=' 6'\t%Oe=' 6'\n"), lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
// Use supplied locale (ja_JP). This locale has a different alternate.
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
check(loc,
SV("%d='06'\t%Od='06'\t%e=' 6'\t%Oe=' 6'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%d='13'\t%Od='13'\t%e='13'\t%Oe='13'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
check(loc,
SV("%d='06'\t%Od='六'\t%e=' 6'\t%Oe='六'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%d='13'\t%Od='十三'\t%e='13'\t%Oe='十三'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values_weekday() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
constexpr std::basic_string_view<CharT> fmt =
SV("{:%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
constexpr std::basic_string_view<CharT> lfmt =
SV("{:L%%a='%a'%t%%A='%A'%t%%u='%u'%t%%Ou='%Ou'%t%%w='%w'%t%%Ow='%Ow'%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%a='Sun'\t%A='Sunday'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
fmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%a='Sun'\t%A='Sunday'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
fmt,
cr::gps_seconds(3'979'002'513s)); // 06:28:15 GPS on Sunday, 7 February 2106
// Use the global locale (fr_FR)
#if defined(__APPLE__)
check(SV("%a='Dim'\t%A='Dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%a='Dim'\t%A='Dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
lfmt,
cr::gps_seconds(3'979'002'513s)); // 06:28:15 GPS on Sunday, 7 February 2106
#else
check(SV("%a='dim.'\t%A='dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%a='dim.'\t%A='dimanche'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
lfmt,
cr::gps_seconds(3'979'002'513s)); // 06:28:15 GPS on Sunday, 7 February 2106
#endif
// Use supplied locale (ja_JP).
// This locale has a different alternate, but not on all platforms
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
check(loc,
SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='7'\t%w='0'\t%Ow='0'\n"),
lfmt,
cr::gps_seconds(3'979'002'513s)); // 06:28:15 GPS on Sunday, 7 February 2106
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
check(loc,
SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='七'\t%w='0'\t%Ow=''\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%a='日'\t%A='日曜日'\t%u='7'\t%Ou='七'\t%w='0'\t%Ow=''\n"),
lfmt,
cr::gps_seconds(3'979'002'513s)); // 06:28:15 GPS on Sunday, 7 February 2106
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values_day_of_year() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
constexpr std::basic_string_view<CharT> fmt = SV("{:%%j='%j'%n}");
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%j='%j'%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%j='006'\n"), fmt, cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%j='138'\n"), fmt, cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
// Use the global locale (fr_FR)
check(SV("%j='006'\n"), lfmt, cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%j='138'\n"), lfmt, cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
// Use supplied locale (ja_JP). This locale has a different alternate.
check(loc, SV("%j='006'\n"), lfmt, cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc, SV("%j='138'\n"), lfmt, cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values_week() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
constexpr std::basic_string_view<CharT> fmt = SV("{:%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%U='%U'%t%%OU='%OU'%t%%W='%W'%t%%OW='%OW'%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%U='01'\t%OU='01'\t%W='00'\t%OW='00'\n"), fmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
fmt,
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
// Use the global locale (fr_FR)
check(SV("%U='01'\t%OU='01'\t%W='00'\t%OW='00'\n"), lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
lfmt,
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
// Use supplied locale (ja_JP). This locale has a different alternate.
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
check(loc,
SV("%U='01'\t%OU='001\t%W='00'\t%OW='00'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%U='20'\t%OU='20'\t%W='20'\t%OW='20'\n"),
lfmt,
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
check(loc,
SV("%U='01'\t%OU='一'\t%W='00'\t%OW=''\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%U='20'\t%OU='二十'\t%W='20'\t%OW='二十'\n"),
lfmt,
cr::gps_seconds(1'684'035'218s)); // 03:33:20 GPS Wednesday, 18 May 2033
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values_iso_8601_week() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
constexpr std::basic_string_view<CharT> fmt = SV("{:%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%g='%g'%t%%G='%G'%t%%V='%V'%t%%OV='%OV'%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%g='80'\t%G='1980'\t%V='01'\t%OV='01'\n"), fmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
fmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
// Use the global locale (fr_FR)
check(SV("%g='80'\t%G='1980'\t%V='01'\t%OV='01'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
// Use supplied locale (ja_JP). This locale has a different alternate.
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
check(loc,
SV("%g='80'\t%G='1980'\t%V='01'\t%OV='01'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%g='09'\t%G='2009'\t%V='07'\t%OV='07'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
check(loc,
SV("%g='80'\t%G='1980'\t%V='01'\t%OV='一'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%g='09'\t%G='2009'\t%V='07'\t%OV='七'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values_date() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
constexpr std::basic_string_view<CharT> fmt = SV("{:%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%D='%D'%t%%F='%F'%t%%x='%x'%t%%Ex='%Ex'%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%D='01/06/80'\t%F='1980-01-06'\t%x='01/06/80'\t%Ex='01/06/80'\n"),
fmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='02/13/09'\t%Ex='02/13/09'\n"),
fmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
// Use the global locale (fr_FR)
#if defined(__APPLE__) || defined(__FreeBSD__)
check(SV("%D='01/06/80'\t%F='1980-01-01'\t%x='06.01.1980'\t%Ex='06.01.1980'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13.02.2009'\t%Ex='13.02.2009'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#else
check(SV("%D='01/06/80'\t%F='1980-01-06'\t%x='06/01/1980'\t%Ex='06/01/1980'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%D='02/13/09'\t%F='2009-02-13'\t%x='13/02/2009'\t%Ex='13/02/2009'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#endif
// Use supplied locale (ja_JP). This locale has a different alternate.
#if defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
check(loc,
SV("%D='01/06/80'\t%F='1980-01-06'\t%x='1980/01/06'\t%Ex='1980/01/06'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009/02/13'\t%Ex='2009/02/13'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#else // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
check(loc,
SV("%D='01/06/80'\t%F='1980-01-06'\t%x='1980年01月06日'\t%Ex='昭和55年01月06日'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%D='02/13/09'\t%F='2009-02-13'\t%x='2009年02月13日'\t%Ex='平成21年02月13日'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#endif // defined(_WIN32) || defined(__APPLE__) || defined(_AIX) || defined(__FreeBSD__)
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values_time() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
constexpr std::basic_string_view<CharT> fmt = SV(
"{:"
"%%H='%H'%t"
"%%OH='%OH'%t"
"%%I='%I'%t"
"%%OI='%OI'%t"
"%%M='%M'%t"
"%%OM='%OM'%t"
"%%S='%S'%t"
"%%OS='%OS'%t"
"%%p='%p'%t"
"%%R='%R'%t"
"%%T='%T'%t"
"%%r='%r'%t"
"%%X='%X'%t"
"%%EX='%EX'%t"
"%n}");
constexpr std::basic_string_view<CharT> lfmt = SV(
"{:L"
"%%H='%H'%t"
"%%OH='%OH'%t"
"%%I='%I'%t"
"%%OI='%OI'%t"
"%%M='%M'%t"
"%%OM='%OM'%t"
"%%S='%S'%t"
"%%OS='%OS'%t"
"%%p='%p'%t"
"%%R='%R'%t"
"%%T='%T'%t"
"%%r='%r'%t"
"%%X='%X'%t"
"%%EX='%EX'%t"
"%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%H='00'\t"
"%OH='00'\t"
"%I='12'\t"
"%OI='12'\t"
"%M='00'\t"
"%OM='00'\t"
"%S='00'\t"
"%OS='00'\t"
"%p='AM'\t"
"%R='00:00'\t"
"%T='00:00:00'\t"
"%r='12:00:00 AM'\t"
"%X='00:00:00'\t"
"%EX='00:00:00'\t"
"\n"),
fmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%H='23'\t"
"%OH='23'\t"
"%I='11'\t"
"%OI='11'\t"
"%M='31'\t"
"%OM='31'\t"
"%S='30.123'\t"
"%OS='30.123'\t"
"%p='PM'\t"
"%R='23:31'\t"
"%T='23:31:30.123'\t"
"%r='11:31:30 PM'\t"
"%X='23:31:30'\t"
"%EX='23:31:30'\t"
"\n"),
fmt,
cr::gps_time<cr::milliseconds>(918'603'105'123ms)); // 23:31:30 GPS Friday, 13 February 2009
// Use the global locale (fr_FR)
check(SV("%H='00'\t"
"%OH='00'\t"
"%I='12'\t"
"%OI='12'\t"
"%M='00'\t"
"%OM='00'\t"
"%S='00'\t"
"%OS='00'\t"
#if defined(_AIX)
"%p='AM'\t"
#else
"%p=''\t"
#endif
"%R='00:00'\t"
"%T='00:00:00'\t"
#ifdef _WIN32
"%r='00:00:00'\t"
#elif defined(_AIX)
"%r='12:00:00 AM'\t"
#elif defined(__APPLE__) || defined(__FreeBSD__)
"%r=''\t"
#else
"%r='12:00:00 '\t"
#endif
"%X='00:00:00'\t"
"%EX='00:00:00'\t"
"\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%H='23'\t"
"%OH='23'\t"
"%I='11'\t"
"%OI='11'\t"
"%M='31'\t"
"%OM='31'\t"
"%S='30,123'\t"
"%OS='30,123'\t"
#if defined(_AIX)
"%p='PM'\t"
#else
"%p=''\t"
#endif
"%R='23:31'\t"
"%T='23:31:30,123'\t"
#ifdef _WIN32
"%r='23:31:30'\t"
#elif defined(_AIX)
"%r='11:31:30 PM'\t"
#elif defined(__APPLE__) || defined(__FreeBSD__)
"%r=''\t"
#else
"%r='11:31:30 '\t"
#endif
"%X='23:31:30'\t"
"%EX='23:31:30'\t"
"\n"),
lfmt,
cr::gps_time<cr::milliseconds>(918'603'105'123ms)); // 23:31:30 GPS Friday, 13 February 2009
// Use supplied locale (ja_JP). This locale has a different alternate.
#if defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
check(loc,
SV("%H='00'\t"
"%OH='00'\t"
"%I='12'\t"
"%OI='12'\t"
"%M='00'\t"
"%OM='00'\t"
"%S='00'\t"
"%OS='00'\t"
# if defined(__APPLE__)
"%p='AM'\t"
# else
"%p='午前'\t"
# endif
"%R='00:00'\t"
"%T='00:00:00'\t"
# if defined(__APPLE__) || defined(__FreeBSD__)
# if defined(__APPLE__)
"%r='12:00:00 AM'\t"
# else
"%r='12:00:00 午前'\t"
# endif
"%X='00時00分00秒'\t"
"%EX='00時00分00秒'\t"
# elif defined(_WIN32)
"%r='0:00:00'\t"
"%X='0:00:00'\t"
"%EX='0:00:00'\t"
# else
"%r='午前12:00:00'\t"
"%X='00:00:00'\t"
"%EX='00:00:00'\t"
# endif
"\n"),
lfmt,
cr::hh_mm_ss(0s));
check(loc,
SV("%H='23'\t"
"%OH='23'\t"
"%I='11'\t"
"%OI='11'\t"
"%M='31'\t"
"%OM='31'\t"
"%S='30.123'\t"
"%OS='30.123'\t"
# if defined(__APPLE__)
"%p='PM'\t"
# else
"%p='午後'\t"
# endif
"%R='23:31'\t"
"%T='23:31:30.123'\t"
# if defined(__APPLE__) || defined(__FreeBSD__)
# if defined(__APPLE__)
"%r='11:31:30 PM'\t"
# else
"%r='11:31:30 午後'\t"
# endif
"%X='23時31分30秒'\t"
"%EX='23時31分30秒'\t"
# elif defined(_WIN32)
"%r='23:31:30'\t"
"%X='23:31:30'\t"
"%EX='23:31:30'\t"
# else
"%r='午後11:31:30'\t"
"%X='23:31:30'\t"
"%EX='23:31:30'\t"
# endif
"\n"),
lfmt,
cr::hh_mm_ss(23h + 31min + 30s + 123ms));
#else // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
check(loc,
SV("%H='00'\t"
"%OH=''\t"
"%I='12'\t"
"%OI='十二'\t"
"%M='00'\t"
"%OM=''\t"
"%S='00'\t"
"%OS=''\t"
"%p='午前'\t"
"%R='00:00'\t"
"%T='00:00:00'\t"
"%r='午前12時00分00秒'\t"
"%X='00時00分00秒'\t"
"%EX='00時00分00秒'\t"
"\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%H='23'\t"
"%OH='二十三'\t"
"%I='11'\t"
"%OI='十一'\t"
"%M='31'\t"
"%OM='三十一'\t"
"%S='30.123'\t"
"%OS='三十.123'\t"
"%p='午後'\t"
"%R='23:31'\t"
"%T='23:31:30.123'\t"
"%r='午後11時31分30秒'\t"
"%X='23時31分30秒'\t"
"%EX='23時31分30秒'\t"
"\n"),
lfmt,
cr::gps_time<cr::milliseconds>(918'603'105'123ms)); // 23:31:30 GPS Friday, 13 February 2009
#endif // defined(__APPLE__) || defined(_AIX) || defined(_WIN32) || defined(__FreeBSD__)
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values_date_time() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
constexpr std::basic_string_view<CharT> fmt = SV("{:%%c='%c'%t%%Ec='%Ec'%n}");
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%c='%c'%t%%Ec='%Ec'%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%c='Sun Jan 6 00:00:00 1980'\t%Ec='Sun Jan 6 00:00:00 1980'\n"),
fmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(SV("%c='Fri Feb 13 23:31:30 2009'\t%Ec='Fri Feb 13 23:31:30 2009'\n"),
fmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
// Use the global locale (fr_FR)
check(
// https://sourceware.org/bugzilla/show_bug.cgi?id=24054
#if defined(__powerpc__) && defined(__linux__)
SV("%c='dim. 06 janv. 1980 00:00:00 GPS'\t%Ec='dim. 06 janv. 1958 00:00:00 GPS'\n"),
#elif defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
SV("%c='dim. 06 janv. 1980 00:00:00 GMT'\t%Ec='dim. 06 janv. 1980 00:00:00 GMT'\n"),
#elif defined(_AIX)
SV("%c=' 1 janvier 1980 à 00:00:00 GPS'\t%Ec=' 6 janvier 1980 à 00:00:00 GPS'\n"),
#elif defined(__APPLE__)
SV("%c='Dim 6 jan 00:00:00 1980'\t%Ec='Dim 6 jan 00:00:00 1980'\n"),
#elif defined(_WIN32)
SV("%c='06/01/1980 00:00:00'\t%Ec='06/01/1980 00:00:00'\n"),
#elif defined(__FreeBSD__)
SV("%c='dim. 6 janv. 00:00:00 1980'\t%Ec='dim. 6 janv. 00:00:00 1980'\n"),
#else
SV("%c='dim. 06 janv. 1980 00:00:00'\t%Ec='dim. 06 janv. 1980 00:00:00'\n"),
#endif
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(
// https://sourceware.org/bugzilla/show_bug.cgi?id=24054
#if defined(__powerpc__) && defined(__linux__)
SV("%c='ven. 13 févr. 2009 23:31:30 GPS'\t%Ec='ven. 13 févr. 2009 23:31:30 GPS'\n"),
#elif defined(__GLIBC__) && __GLIBC__ <= 2 && __GLIBC_MINOR__ < 29
SV("%c='ven. 13 févr. 2009 23:31:30 GMT'\t%Ec='ven. 13 févr. 2009 23:31:30 GMT'\n"),
#elif defined(_AIX)
SV("%c='13 février 2009 à 23:31:30 GPS'\t%Ec='13 février 2009 à 23:31:30 GPS'\n"),
#elif defined(__APPLE__)
SV("%c='Ven 13 fév 23:31:30 2009'\t%Ec='Ven 13 fév 23:31:30 2009'\n"),
#elif defined(_WIN32)
SV("%c='13/02/2009 23:31:30'\t%Ec='13/02/2009 23:31:30'\n"),
#elif defined(__FreeBSD__)
SV("%c='ven. 13 févr. 23:31:30 2009'\t%Ec='ven. 13 févr. 23:31:30 2009'\n"),
#else
SV("%c='ven. 13 févr. 2009 23:31:30'\t%Ec='ven. 13 févr. 2009 23:31:30'\n"),
#endif
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
// Use supplied locale (ja_JP). This locale has a different alternate.a
#if defined(__APPLE__) || defined(__FreeBSD__)
check(loc,
SV("%c='水 1/ 6 00:00:00 1980'\t%Ec='水 1/ 6 00:00:00 1980'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%c='金 2/13 23:31:30 2009'\t%Ec='金 2/13 23:31:30 2009'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#elif defined(_AIX) // defined(__APPLE__)|| defined(__FreeBSD__)
check(loc,
SV("%c='1980年01月 6日 00:00:00 GPS'\t%Ec='1980年01月 6日 00:00:00 GPS'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%c='2009年02月13日 23:31:30 GPS'\t%Ec='2009年02月13日 23:31:30 GPS'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#elif defined(_WIN32) // defined(__APPLE__)|| defined(__FreeBSD__)
check(loc,
SV("%c='1980/01/06 0:00:00'\t%Ec='1980/01/06 0:00:00'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%c='2009/02/13 23:31:30'\t%Ec='2009/02/13 23:31:30'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#else // defined(__APPLE__)|| defined(__FreeBSD__)
check(loc,
SV("%c='1980年01月06日 00時00分00秒'\t%Ec='昭和55年01月06日 00時00分00秒'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
check(loc,
SV("%c='2009年02月13日 23時31分30秒'\t%Ec='平成21年02月13日 23時31分30秒'\n"),
lfmt,
cr::gps_seconds(918'603'105s)); // 23:31:30 GPS Friday, 13 February 2009
#endif // defined(__APPLE__)|| defined(__FreeBSD__)
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values_time_zone() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
constexpr std::basic_string_view<CharT> fmt = SV("{:%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");
constexpr std::basic_string_view<CharT> lfmt = SV("{:L%%z='%z'%t%%Ez='%Ez'%t%%Oz='%Oz'%t%%Z='%Z'%n}");
const std::locale loc(LOCALE_ja_JP_UTF_8);
std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
// Non localized output using C-locale
check(SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='GPS'\n"),
fmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
// Use the global locale (fr_FR)
check(SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='GPS'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
// Use supplied locale (ja_JP).
check(loc,
SV("%z='+0000'\t%Ez='+00:00'\t%Oz='+00:00'\t%Z='GPS'\n"),
lfmt,
cr::gps_seconds(0s)); // 00:00:00 GPS Sunday, 6 January 1980
std::locale::global(std::locale::classic());
}
template <class CharT>
static void test_valid_values() {
test_valid_values_year<CharT>();
test_valid_values_month<CharT>();
test_valid_values_day<CharT>();
test_valid_values_weekday<CharT>();
test_valid_values_day_of_year<CharT>();
test_valid_values_week<CharT>();
test_valid_values_iso_8601_week<CharT>();
test_valid_values_date<CharT>();
test_valid_values_time<CharT>();
test_valid_values_date_time<CharT>();
test_valid_values_time_zone<CharT>();
}
template <class CharT>
static void test() {
using namespace std::literals::chrono_literals;
namespace cr = std::chrono;
test_no_chrono_specs<CharT>();
test_valid_values<CharT>();
check_invalid_types<CharT>(
{SV("a"), SV("A"), SV("b"), SV("B"), SV("c"), SV("C"), SV("d"), SV("D"), SV("e"), SV("F"), SV("g"),
SV("G"), SV("h"), SV("H"), SV("I"), SV("j"), SV("m"), SV("M"), SV("p"), SV("r"), SV("R"), SV("S"),
SV("T"), SV("u"), SV("U"), SV("V"), SV("w"), SV("W"), SV("x"), SV("X"), SV("y"), SV("Y"), SV("z"),
SV("Z"), SV("Ec"), SV("EC"), SV("Ex"), SV("EX"), SV("Ey"), SV("EY"), SV("Ez"), SV("Od"), SV("Oe"), SV("OH"),
SV("OI"), SV("Om"), SV("OM"), SV("OS"), SV("Ou"), SV("OU"), SV("OV"), SV("Ow"), SV("OW"), SV("Oy"), SV("Oz")},
cr::gps_seconds(0s));
check_exception("The format specifier expects a '%' or a '}'", SV("{:A"), cr::gps_seconds(0s));
check_exception("The chrono specifiers contain a '{'", SV("{:%%{"), cr::gps_seconds(0s));
check_exception("End of input while parsing a conversion specifier", SV("{:%"), cr::gps_seconds(0s));
check_exception("End of input while parsing the modifier E", SV("{:%E"), cr::gps_seconds(0s));
check_exception("End of input while parsing the modifier O", SV("{:%O"), cr::gps_seconds(0s));
// Precision not allowed
check_exception("The format specifier expects a '%' or a '}'", SV("{:.3}"), cr::gps_seconds(0s));
}
int main(int, char**) {
test<char>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<wchar_t>();
#endif
return 0;
}