From c0beeb5f0b3285fd7b411859bd68d44b472ad034 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 14 Apr 2016 16:20:59 +0300 Subject: Add timestamp from_string() --- tests/buildfile | 2 +- tests/timestamp/buildfile | 7 ++ tests/timestamp/driver.cxx | 159 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 tests/timestamp/buildfile create mode 100644 tests/timestamp/driver.cxx (limited to 'tests') diff --git a/tests/buildfile b/tests/buildfile index 0ad40e5..45c78d6 100644 --- a/tests/buildfile +++ b/tests/buildfile @@ -2,6 +2,6 @@ # copyright : Copyright (c) 2014-2016 Code Synthesis Ltd # license : MIT; see accompanying LICENSE file -d = dir-iterator/ path/ prefix-map/ sha256/ triplet/ +d = dir-iterator/ path/ prefix-map/ sha256/ timestamp/ triplet/ .: $d include $d diff --git a/tests/timestamp/buildfile b/tests/timestamp/buildfile new file mode 100644 index 0000000..bb565a2 --- /dev/null +++ b/tests/timestamp/buildfile @@ -0,0 +1,7 @@ +# file : tests/timestamp/buildfile +# copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +# license : MIT; see accompanying LICENSE file + +exe{driver}: cxx{driver} ../../butl/lib{butl} + +include ../../butl/ diff --git a/tests/timestamp/driver.cxx b/tests/timestamp/driver.cxx new file mode 100644 index 0000000..2db726d --- /dev/null +++ b/tests/timestamp/driver.cxx @@ -0,0 +1,159 @@ +// file : tests/timestamp/driver.cxx -*- C++ -*- +// copyright : Copyright (c) 2014-2016 Code Synthesis Ltd +// license : MIT; see accompanying LICENSE file + +#include // tzset() + +#include +#include +#include +#include +#include +#include + +#include + +using namespace std; +using namespace butl; + +// Parse the input using the format string. Print the resulted time with the +// same format string, ensure the output matches the input. +// +static bool +parse (const char* in, const char* fmt, bool local, const char* out) +{ + if (out == nullptr) + out = in; + + try + { + const char* e; + timestamp t (from_string (in, fmt, local, &e)); + + ostringstream o; + if (!to_stream (o, t, fmt, false, local)) + return false; + + return o.str () + e == out; + } + catch (...) + { + return false; + } +} + +static bool +parse (const char* in, const char* fmt, const char* out = nullptr) +{ + return parse (in, fmt, true, out) && parse (in, fmt, false, out); +} + +static bool +fail (const char* in, const char* fmt) +{ + try + { + from_string (in, fmt, true); + return false; + } + catch (const system_error&) + { + return true; + } +} + +int +main () +{ + tzset (); // To use butl::to_stream() later on. + + // Invalid %[]. + // + assert (fail ("Apr 08 19:31:10 2016", "%b %d %H:%M:%S%[")); + assert (fail ("Apr 08 19:31:10 2016", "%b %d %H:%M:%S%[.")); + assert (fail ("Apr 08 19:31:10 2016", "%b %d %H:%M:%S%[.U")); + assert (fail ("Apr 08 19:31:10 2016", "%b %d %H:%M:%S%[.A]")); + assert (fail ("Apr 08 19:31:10 2016", "%d %H:%M:%S%[.U] %Y")); + assert (fail ("2016-10-20 11:12:13.123456789", "%Y-%m-%d %H:%M:%S%[N]")); + + // Invalid fraction of a second. + // + assert (fail ("Apr 08 19:31:10. 2016", "%b %d %H:%M:%S%[.U] %Y")); + assert (fail ("Apr 08 19:31:10.1 2016", "%b %d %H:%M:%S%[.M] %Y")); + assert (fail ("Apr 08 19:31:10.12 2016", "%b %d %H:%M:%S%[.M] %Y")); + assert (fail ("Apr 08 19:31:10.", "%b %d %H:%M:%S%[.U] %Y")); + assert (fail ("Apr 08 19:31:10.1", "%b %d %H:%M:%S%[.M] %Y")); + assert (fail ("Apr 08 19:31:10.12", "%b %d %H:%M:%S%[.M] %Y")); + + // Input is not fully parsed. + // + assert (fail ( + "Feb 21 19:31:10.123456789 2016 GMT", "%b %d %H:%M:%S%[.N] %Y")); + + // Invalid input (%[] unrelated). + // + assert (fail ("Apr 08 19:31:10.123456789 ABC", "%b %d %H:%M:%S%[.N] %Y")); + assert (fail ("Apr 19:31:10 2016", "%b %d %H:%M:%S %Y")); + assert (fail ("Opr 08 19:31:10 2016", "%b %d %H:%M:%S %Y")); + + // Parse valid input with a valid format. + // + assert (parse ( + "Apr 18 19:31:10 2016", "%b %d %H:%M:%S %Y", "Apr 18 19:31:10 2016")); + + assert (parse ("Apr 08 19:31:10 2016", "%b %d %H:%M:%S %Y")); + assert (parse ("2016-04-08 19:31:10", "%Y-%m-%d %H:%M:%S")); + + assert (parse ("ABC=Apr 18 19:31:10 2016 ABC", "ABC=%b %d %H:%M:%S %Y")); + assert (parse ("ABC=2016-04-08 19:31:10 ABC", "ABC=%Y-%m-%d %H:%M:%S")); + + assert (parse ("Feb 11 19:31:10 2016 GMT", "%b %d %H:%M:%S%[.N] %Y")); + assert (parse ("2016-02-11 19:31:10 GMT", "%Y-%m-%d %H:%M:%S%[.N]")); + + assert (parse ( + "Feb 21 19:31:10.384902285 2016 GMT", "%b %d %H:%M:%S%[.N] %Y")); + assert (parse ( + "2016-02-21 19:31:10.384902285 GMT", "%Y-%m-%d %H:%M:%S%[.N]")); + + assert (parse ( + "Feb 21 19:31:10 .384902285 2016 GMT", "%b %d %H:%M:%S %[.N] %Y")); + assert (parse ( + "2016-02-21 19:31:10 .384902285 GMT", "%Y-%m-%d %H:%M:%S %[.N]")); + + assert (parse ( + "2016-02-21 19:31:10 .384902285 GMT", + "%Y-%m-%d %H:%M:%S %[.N]", + "2016-02-21 19:31:10 .384902285 GMT")); + + assert (parse ( + "2016-02-21 19:31:10 .384902285 GMT", + "%Y-%m-%d %H:%M:%S %[.N]", + "2016-02-21 19:31:10 .384902285 GMT")); + + assert (parse ( + "Feb 21 19:31:10 .384902285NS 2016 GMT", "%b %d %H:%M:%S %[.N]NS %Y")); + assert (parse ( + "2016-02-21 19:31:10 .384902285NS GMT", "%Y-%m-%d %H:%M:%S %[.N]NS")); + + assert (parse ( + ".384902285 Feb 21 19:31:10 2016", "%[.N] %b %d %H:%M:%S %Y")); + assert (parse ( + ".384902285 2016-02-21 19:31:10", "%[.N] %Y-%m-%d %H:%M:%S")); + assert (parse ( + ".3849022852016-02-21 19:31:10", "%[.N]%Y-%m-%d %H:%M:%S")); + + setlocale (LC_ALL, "de_DE.utf-8"); + locale::global (locale ("de_DE.utf-8")); + assert (parse ("Mai 11 19:31:10 2016 GMT", "%b %d %H:%M:%S%[.N] %Y")); + locale::global (locale ("C")); + + // @@ When debuging strptime() fallback implementation compiled with GCC + // 5.3.1, the following asserts will fail due to bugs in implementation + // of std::get_time() manipulator. So need to be commented out. + // + assert (fail ("Apr 08 19:31:10 2016", "%b %d %H:%M:%S %Y %")); + assert (fail ("Apr 08 19:31:10", "%b %d %H:%M:%S %Y")); + + assert (parse ( + "Apr 8 19:31:10 2016", "%b %d %H:%M:%S %Y", "Apr 08 19:31:10 2016")); +} -- cgit v1.1