Skip to content

Commit f167ddd

Browse files
committed
Change Timestamp type to a better one supported in Windows
1 parent d16a1e1 commit f167ddd

5 files changed

Lines changed: 94 additions & 80 deletions

File tree

src/lib/CalendarConverter.h

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -370,30 +370,29 @@ namespace fbcpp::impl
370370
// FIXME: review
371371
OpaqueTimestamp timestampToOpaqueTimestamp(const Timestamp& timestamp)
372372
{
373-
const auto date = timestampDate(timestamp);
373+
const auto& date = timestamp.date;
374374
if (!date.ok())
375375
throwInvalidTimestampValue();
376376

377377
const auto opaqueDate = dateToOpaqueDate(date);
378378

379-
const auto timeOfDay = timestampTimeOfDay(timestamp);
379+
const auto timeOfDay = timestamp.time.to_duration();
380380
if (timeOfDay.count() < 0 || timeOfDay >= std::chrono::hours{24})
381381
throwInvalidTimestampValue();
382382

383-
const std::chrono::hh_mm_ss timeBreakdown{timeOfDay};
384-
if (timeBreakdown.is_negative())
383+
if (timestamp.time.is_negative())
385384
throwInvalidTimestampValue();
386385

387-
const auto subseconds = timeBreakdown.subseconds().count();
386+
const auto subseconds = timestamp.time.subseconds().count();
388387
if (subseconds % 100 != 0)
389388
throwInvalidTimestampValue();
390389

391390
OpaqueTimestamp opaqueTimestamp;
392391
opaqueTimestamp.value.timestamp_date = opaqueDate.value;
393392
opaqueTimestamp.value.timestamp_time =
394-
client.getUtil()->encodeTime(static_cast<unsigned>(timeBreakdown.hours().count()),
395-
static_cast<unsigned>(timeBreakdown.minutes().count()),
396-
static_cast<unsigned>(timeBreakdown.seconds().count()), static_cast<unsigned>(subseconds / 100));
393+
client.getUtil()->encodeTime(static_cast<unsigned>(timestamp.time.hours().count()),
394+
static_cast<unsigned>(timestamp.time.minutes().count()),
395+
static_cast<unsigned>(timestamp.time.seconds().count()), static_cast<unsigned>(subseconds / 100));
397396

398397
return opaqueTimestamp;
399398
}
@@ -421,7 +420,7 @@ namespace fbcpp::impl
421420
if (!date.ok())
422421
throwInvalidTimestampValue();
423422

424-
return std::chrono::local_days{date} + timeOfDay;
423+
return Timestamp{date, Time{timeOfDay}};
425424
}
426425

427426
Timestamp stringToTimestamp(std::string_view value)
@@ -489,7 +488,7 @@ namespace fbcpp::impl
489488
if (timeOfDay >= std::chrono::hours{24})
490489
throwInvalidTimestampValue();
491490

492-
return std::chrono::local_days{date} + timeOfDay;
491+
return Timestamp{date, Time{timeOfDay}};
493492
}
494493

495494
OpaqueTimestamp stringToOpaqueTimestamp(std::string_view value)
@@ -500,28 +499,17 @@ namespace fbcpp::impl
500499
std::string opaqueTimestampToString(OpaqueTimestamp timestamp)
501500
{
502501
const auto converted = opaqueTimestampToTimestamp(timestamp);
503-
const std::chrono::hh_mm_ss timeBreakdown{timestampTimeOfDay(converted)};
504-
const auto subseconds = static_cast<unsigned>(timeBreakdown.subseconds().count() / 100);
502+
const auto subseconds = static_cast<unsigned>(converted.time.subseconds().count() / 100);
505503

506-
const auto dateString = std::format("{:%Y-%m-%d}", std::chrono::local_days{timestampDate(converted)});
504+
const auto dateString = std::format("{:%Y-%m-%d}", std::chrono::local_days{converted.date});
507505
const auto timeString =
508-
std::format("{:02}:{:02}:{:02}.{:04}", static_cast<unsigned>(timeBreakdown.hours().count()),
509-
static_cast<unsigned>(timeBreakdown.minutes().count()),
510-
static_cast<unsigned>(timeBreakdown.seconds().count()), subseconds);
506+
std::format("{:02}:{:02}:{:02}.{:04}", static_cast<unsigned>(converted.time.hours().count()),
507+
static_cast<unsigned>(converted.time.minutes().count()),
508+
static_cast<unsigned>(converted.time.seconds().count()), subseconds);
511509

512510
return std::format("{} {}", dateString, timeString);
513511
}
514512

515-
Date timestampDate(const Timestamp& timestamp)
516-
{
517-
return Date{std::chrono::floor<std::chrono::days>(timestamp)};
518-
}
519-
520-
std::chrono::microseconds timestampTimeOfDay(const Timestamp& timestamp)
521-
{
522-
return timestamp - std::chrono::floor<std::chrono::days>(timestamp);
523-
}
524-
525513
OpaqueTimestampTz timestampTzToOpaqueTimestampTz(const TimestampTz& timestampTz)
526514
{
527515
OpaqueTimestampTz opaque;
@@ -562,7 +550,8 @@ namespace fbcpp::impl
562550
&minutes, &seconds, &subseconds, static_cast<unsigned>(sizeof(timeZoneBuffer)), timeZoneBuffer);
563551

564552
TimestampTz timestampTz;
565-
timestampTz.utcTimestamp = BASE_EPOCH + std::chrono::microseconds{ticks};
553+
const auto utcLocalTime = BASE_EPOCH + std::chrono::microseconds{ticks};
554+
timestampTz.utcTimestamp = Timestamp::fromLocalTime(utcLocalTime);
566555
timestampTz.zone = timeZoneBuffer;
567556

568557
if (decodedTimeZoneName)
@@ -659,7 +648,7 @@ namespace fbcpp::impl
659648
if (timeOfDay >= std::chrono::hours{24})
660649
throwInvalidTimestampValue();
661650

662-
const Timestamp localTimestamp = std::chrono::local_days{date} + timeOfDay;
651+
const Timestamp localTimestamp{date, Time{timeOfDay}};
663652

664653
const auto monthValue = static_cast<unsigned>(date.month());
665654
const auto dayValue = static_cast<unsigned>(date.day());
@@ -673,7 +662,7 @@ namespace fbcpp::impl
673662
const OpaqueTimestamp utcOpaque{encoded.value.utc_timestamp};
674663
const auto utcTimestamp = opaqueTimestampToTimestamp(utcOpaque);
675664

676-
const auto offsetDuration = localTimestamp - utcTimestamp;
665+
const auto offsetDuration = localTimestamp.toLocalTime() - utcTimestamp.toLocalTime();
677666
if (offsetDuration % std::chrono::minutes{1} != std::chrono::microseconds::zero())
678667
throwInvalidTimestampValue();
679668

src/lib/types.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,36 @@ namespace fbcpp
6969

7070
using Date = std::chrono::year_month_day;
7171
using Time = std::chrono::hh_mm_ss<std::chrono::microseconds>;
72-
using Timestamp = std::chrono::local_time<std::chrono::microseconds>; // FIXME: MSVC support range
72+
73+
struct Timestamp final
74+
{
75+
bool operator==(const Timestamp& other) const noexcept
76+
{
77+
return date == other.date && time.to_duration() == other.time.to_duration();
78+
}
79+
80+
///
81+
/// Converts to std::chrono::local_time<std::chrono::microseconds>.
82+
/// Important: in Windows, std::chrono::local_time<std::chrono::microseconds> cannot represent all the valid
83+
/// date range supported by Firebird.
84+
///
85+
std::chrono::local_time<std::chrono::microseconds> toLocalTime() const noexcept
86+
{
87+
return std::chrono::local_days{date} + time.to_duration();
88+
}
89+
90+
static Timestamp fromLocalTime(std::chrono::local_time<std::chrono::microseconds> value) noexcept
91+
{
92+
const auto days = std::chrono::floor<std::chrono::days>(value);
93+
const Date dateValue{days};
94+
const auto timeOfDay = std::chrono::duration_cast<std::chrono::microseconds>(value - days);
95+
96+
return Timestamp{dateValue, Time{timeOfDay}};
97+
}
98+
99+
Date date{};
100+
Time time{std::chrono::microseconds::zero()};
101+
};
73102

74103
struct TimeTz final
75104
{

src/test/CalendarConverter.cpp

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ namespace data = boost::unit_test::data;
3838
using namespace std::chrono;
3939
using namespace std::chrono_literals;
4040

41-
42-
static const auto spTz = locate_zone("America/Sao_Paulo");
43-
static const auto utcTz = locate_zone("UTC");
44-
4541
namespace
4642
{
4743
template <typename T>
@@ -76,8 +72,7 @@ namespace
7672

7773
struct TimeTzCase final
7874
{
79-
Time time;
80-
std::string_view zone;
75+
TimeTz timeTz;
8176
std::string_view outputText;
8277
std::optional<std::string_view> inputText = std::nullopt;
8378
};
@@ -90,8 +85,7 @@ namespace
9085

9186
struct TimestampTzCase final
9287
{
93-
Timestamp timestamp;
94-
std::string_view zone;
88+
TimestampTz timestampTz;
9589
std::string_view outputText;
9690
std::optional<std::string_view> inputText = std::nullopt;
9791
};
@@ -166,9 +160,9 @@ BOOST_DATA_TEST_CASE(timeConversion, data::make(TIME_CASES), timeCase)
166160

167161

168162
static const std::initializer_list<TimestampCase> TIMESTAMP_CASES{
169-
{Timestamp{local_days{2024y / month{2} / 29d} + 13h + 14min + 15s + 123400us}, "2024-02-29 13:14:15.1234"},
170-
{Timestamp{local_days{1y / month{1} / 1d} + microseconds::zero()}, "0001-01-01 00:00:00.0000"},
171-
{Timestamp{local_days{9999y / month{12} / 31d} + 23h + 59min + 59s + 999900us}, "9999-12-31 23:59:59.9999",
163+
{Timestamp{Date{2024y / month{2} / 29d}, Time{13h + 14min + 15s + 123400us}}, "2024-02-29 13:14:15.1234"},
164+
{Timestamp{Date{1y / month{1} / 1d}, Time{microseconds::zero()}}, "0001-01-01 00:00:00.0000"},
165+
{Timestamp{Date{9999y / month{12} / 31d}, Time{23h + 59min + 59s + 999900us}}, "9999-12-31 23:59:59.9999",
172166
" 9999 - 12 - 31 23 : 59 : 59 . 9999 "},
173167
};
174168

@@ -196,9 +190,9 @@ BOOST_DATA_TEST_CASE(timestampConversion, data::make(TIMESTAMP_CASES), timestamp
196190

197191

198192
static const std::initializer_list<TimeTzCase> TIME_TZ_CASES{
199-
{Time{13h + 14min + 15s + 123400us}, "America/Sao_Paulo", "13:14:15.1234 America/Sao_Paulo"},
200-
{Time{0us}, "America/Sao_Paulo", "00:00:00.0000 America/Sao_Paulo"},
201-
{Time{23h + 59min + 59s + 999900us}, "America/Sao_Paulo", "23:59:59.9999 America/Sao_Paulo",
193+
{TimeTz{Time{16h + 14min + 15s + 123400us}, "America/Sao_Paulo"}, "13:14:15.1234 America/Sao_Paulo"},
194+
{TimeTz{Time{3h}, "America/Sao_Paulo"}, "00:00:00.0000 America/Sao_Paulo"},
195+
{TimeTz{Time{2h + 59min + 59s + 999900us}, "America/Sao_Paulo"}, "23:59:59.9999 America/Sao_Paulo",
202196
" 23 : 59 : 59 . 9999 America/Sao_Paulo "},
203197
};
204198

@@ -209,10 +203,7 @@ BOOST_DATA_TEST_CASE(timeTzConversion, data::make(TIME_TZ_CASES), timeTzCase)
209203

210204
impl::CalendarConverter converter{CLIENT, &statusWrapper};
211205

212-
const Date baseTimeTzDate{year{2020}, month{1}, 1d};
213-
const Timestamp localTimestamp{local_days{baseTimeTzDate} + timeTzCase.time.to_duration()};
214-
const auto localTimestampUtc = utcTz->to_local(spTz->to_sys(localTimestamp));
215-
const TimeTz timeTz{Time{localTimestampUtc - floor<days>(localTimestampUtc)}, std::string{timeTzCase.zone}};
206+
const TimeTz& timeTz = timeTzCase.timeTz;
216207
const std::string outputText{timeTzCase.outputText};
217208
const std::string inputText{timeTzCase.inputText.value_or(outputText)};
218209

@@ -251,11 +242,12 @@ BOOST_DATA_TEST_CASE(timeTzOffsetConversion, data::make(TIME_TZ_OFFSET_CASES), t
251242

252243

253244
static const std::initializer_list<TimestampTzCase> TIMESTAMP_TZ_CASES{
254-
{Timestamp{local_days{2024y / month{2} / 29d} + 13h + 14min + 15s + 123400us}, "America/Sao_Paulo",
245+
{TimestampTz{Timestamp{Date{2024y / month{2} / 29d}, Time{16h + 14min + 15s + 123400us}}, "America/Sao_Paulo"},
255246
"2024-02-29 13:14:15.1234 America/Sao_Paulo"},
256-
{Timestamp{local_days{1y / month{1} / 1d} + 13h + 14min + 15s + 123400us}, "UTC", "0001-01-01 13:14:15.1234 UTC"},
257-
{Timestamp{local_days{9999y / month{12} / 31d} + 23h + 59min + 59s + 999900us}, "America/Sao_Paulo",
258-
"9999-12-31 23:59:59.9999 America/Sao_Paulo", " 9999 - 12 - 31 23 : 59 : 59 . 9999 America/Sao_Paulo "},
247+
{TimestampTz{Timestamp{Date{1y / month{1} / 1d}, Time{13h + 14min + 15s + 123400us}}, "UTC"},
248+
"0001-01-01 13:14:15.1234 UTC"},
249+
{TimestampTz{Timestamp{Date{year{9999}, month{12}, 31d}, Time{23h + 59min + 59s + 999900us}}, "America/Sao_Paulo"},
250+
"9999-12-31 20:59:59.9999 America/Sao_Paulo", " 9999 - 12 - 31 20 : 59 : 59 . 9999 America/Sao_Paulo "},
259251
};
260252

261253
BOOST_DATA_TEST_CASE(timestampTzConversion, data::make(TIMESTAMP_TZ_CASES), timestampTzCase)
@@ -265,10 +257,7 @@ BOOST_DATA_TEST_CASE(timestampTzConversion, data::make(TIMESTAMP_TZ_CASES), time
265257

266258
impl::CalendarConverter converter{CLIENT, &statusWrapper};
267259

268-
auto utcTimestamp = timestampTzCase.timestamp;
269-
if (timestampTzCase.zone != "UTC")
270-
utcTimestamp = utcTz->to_local(spTz->to_sys(timestampTzCase.timestamp));
271-
const TimestampTz timestampTz{utcTimestamp, std::string{timestampTzCase.zone}};
260+
const TimestampTz& timestampTz = timestampTzCase.timestampTz;
272261
const std::string outputText{timestampTzCase.outputText};
273262
const std::string inputText{timestampTzCase.inputText.value_or(outputText)};
274263

src/test/Statement.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -614,13 +614,14 @@ BOOST_AUTO_TEST_CASE(timestampType)
614614
"select timestamp '2024-02-29 13:14:15.1234', timestamp '2023-12-31 23:59:59' from rdb$database "
615615
"where cast(? as timestamp) = timestamp '2024-02-29 13:14:15.1234'"};
616616

617-
const auto february29 =
618-
std::chrono::local_days{Date{std::chrono::year{2024}, std::chrono::month{2}, std::chrono::day{29}}} +
619-
std::chrono::hours{13} + std::chrono::minutes{14} + std::chrono::seconds{15} +
617+
const auto february29Time = std::chrono::hours{13} + std::chrono::minutes{14} + std::chrono::seconds{15} +
620618
std::chrono::microseconds{123400};
621-
const auto december31 =
622-
std::chrono::local_days{Date{std::chrono::year{2023}, std::chrono::month{12}, std::chrono::day{31}}} +
623-
std::chrono::hours{23} + std::chrono::minutes{59} + std::chrono::seconds{59};
619+
const Timestamp february29{Date{std::chrono::year{2024}, std::chrono::month{2}, std::chrono::day{29}},
620+
Time{std::chrono::duration_cast<std::chrono::microseconds>(february29Time)}};
621+
const auto december31Time =
622+
std::chrono::hours{23} + std::chrono::minutes{59} + std::chrono::seconds{59} + std::chrono::microseconds{0};
623+
const Timestamp december31{Date{std::chrono::year{2023}, std::chrono::month{12}, std::chrono::day{31}},
624+
Time{std::chrono::duration_cast<std::chrono::microseconds>(december31Time)}};
624625

625626
statement.setTimestamp(0, february29);
626627
BOOST_CHECK(statement.execute(transaction));
@@ -660,7 +661,7 @@ BOOST_AUTO_TEST_CASE(timestampTzType)
660661
return value.utcTimestamp;
661662

662663
if (value.zone == "America/Sao_Paulo")
663-
return value.utcTimestamp - std::chrono::hours{3};
664+
return Timestamp::fromLocalTime(value.utcTimestamp.toLocalTime() - std::chrono::hours{3});
664665

665666
BOOST_FAIL("Unexpected time zone in test");
666667
return value.utcTimestamp;
@@ -671,19 +672,23 @@ BOOST_AUTO_TEST_CASE(timestampTzType)
671672
return TimestampTz{local, std::string{zone}};
672673

673674
if (zone == "America/Sao_Paulo")
674-
return TimestampTz{local + std::chrono::hours{3}, std::string{zone}};
675+
{
676+
const auto utcLocal = local.toLocalTime() + std::chrono::hours{3};
677+
return TimestampTz{Timestamp::fromLocalTime(utcLocal), std::string{zone}};
678+
}
675679

676680
BOOST_FAIL("Unexpected time zone in test");
677681
return TimestampTz{};
678682
};
679683

680-
const Timestamp utcLocal =
681-
std::chrono::local_days{Date{std::chrono::year{2024}, std::chrono::month{2}, std::chrono::day{29}}} +
682-
std::chrono::hours{13} + std::chrono::minutes{14} + std::chrono::seconds{15} +
684+
const auto utcLocalTime = std::chrono::hours{13} + std::chrono::minutes{14} + std::chrono::seconds{15} +
683685
std::chrono::microseconds{123400};
684-
const Timestamp saoPauloLocal =
685-
std::chrono::local_days{Date{std::chrono::year{2023}, std::chrono::month{12}, std::chrono::day{31}}} +
686-
std::chrono::hours{23} + std::chrono::minutes{59} + std::chrono::seconds{59};
686+
const Timestamp utcLocal{Date{std::chrono::year{2024}, std::chrono::month{2}, std::chrono::day{29}},
687+
Time{std::chrono::duration_cast<std::chrono::microseconds>(utcLocalTime)}};
688+
const auto saoPauloLocalTime =
689+
std::chrono::hours{23} + std::chrono::minutes{59} + std::chrono::seconds{59} + std::chrono::microseconds{0};
690+
const Timestamp saoPauloLocal{Date{std::chrono::year{2023}, std::chrono::month{12}, std::chrono::day{31}},
691+
Time{std::chrono::duration_cast<std::chrono::microseconds>(saoPauloLocalTime)}};
687692
const auto utcTimestampTz = makeTimestampTz("UTC", utcLocal);
688693
const auto saoPauloTimestampTz = makeTimestampTz("America/Sao_Paulo", saoPauloLocal);
689694

@@ -2244,9 +2249,10 @@ BOOST_AUTO_TEST_CASE(opaqueTimestampType)
22442249

22452250
impl::CalendarConverter converter{CLIENT, &statusWrapper};
22462251

2247-
const auto date = std::chrono::year{2024} / std::chrono::month{2} / std::chrono::day{29};
2248-
const Timestamp timestamp = std::chrono::local_days{date} + std::chrono::hours{12} + std::chrono::minutes{34} +
2249-
std::chrono::seconds{56} + std::chrono::microseconds{789100};
2252+
const Date date{std::chrono::year{2024}, std::chrono::month{2}, std::chrono::day{29}};
2253+
const auto timeOfDay = std::chrono::hours{12} + std::chrono::minutes{34} + std::chrono::seconds{56} +
2254+
std::chrono::microseconds{789100};
2255+
const Timestamp timestamp{date, Time{std::chrono::duration_cast<std::chrono::microseconds>(timeOfDay)}};
22502256
const auto opaqueTimestamp = converter.timestampToOpaqueTimestamp(timestamp);
22512257
statement.setOpaqueTimestamp(0, opaqueTimestamp);
22522258
BOOST_CHECK(statement.execute(transaction));
@@ -2282,11 +2288,11 @@ BOOST_AUTO_TEST_CASE(opaqueTimestampTzType)
22822288

22832289
const auto fetchedOpaqueTimestampTz = statement.getOpaqueTimestampTz(0).value();
22842290
const auto roundTripTimestampTz = converter.opaqueTimestampTzToTimestampTz(fetchedOpaqueTimestampTz);
2285-
BOOST_CHECK(roundTripTimestampTz.utcTimestamp.time_since_epoch() == timestampTz.utcTimestamp.time_since_epoch());
2291+
BOOST_CHECK(roundTripTimestampTz.utcTimestamp.toLocalTime() == timestampTz.utcTimestamp.toLocalTime());
22862292
BOOST_CHECK_EQUAL(roundTripTimestampTz.zone, timestampTz.zone);
22872293

22882294
const auto fetchedTimestampTz = statement.getTimestampTz(0).value();
2289-
BOOST_CHECK(fetchedTimestampTz.utcTimestamp.time_since_epoch() == timestampTz.utcTimestamp.time_since_epoch());
2295+
BOOST_CHECK(fetchedTimestampTz.utcTimestamp.toLocalTime() == timestampTz.utcTimestamp.toLocalTime());
22902296
BOOST_CHECK_EQUAL(fetchedTimestampTz.zone, timestampTz.zone);
22912297
BOOST_CHECK_EQUAL(statement.getString(0).value(), "2024-02-29 12:34:56.7891 America/Sao_Paulo");
22922298

src/test/Statement2.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -350,10 +350,11 @@ BOOST_AUTO_TEST_CASE(parameterBindingAndGetters)
350350

351351
const Date dateValue{2024y / March / 15d};
352352
const Time timeValue{13h + 14min + 15s + 123456us};
353-
const Timestamp timestampValue{local_days{2024y / March / 15d} + 10h + 11min + 12s + 654321us};
353+
const auto timestampDuration = 10h + 11min + 12s + 654321us;
354+
const Timestamp timestampValue{Date{2024y / March / 15d}, Time{timestampDuration}};
354355
const TimeTz timeTzValue{Time{7h + 8min + 9s + 111222us}, "UTC"};
355-
const TimestampTz timestampTzValue{
356-
Timestamp{local_days{2024y / March / 16d} + 5h + 6min + 7s + 333444us}, "UTC"};
356+
const auto timestampTzDuration = 5h + 6min + 7s + 333444us;
357+
const TimestampTz timestampTzValue{Timestamp{Date{2024y / March / 16d}, Time{timestampTzDuration}}, "UTC"};
357358

358359
const OpaqueDate opaqueDateValue = calendarConverter.dateToOpaqueDate(dateValue);
359360
const OpaqueTime opaqueTimeValue = calendarConverter.timeToOpaqueTime(timeValue);
@@ -719,8 +720,8 @@ BOOST_AUTO_TEST_CASE(stringConversions)
719720
BOOST_CHECK_EQUAL(selectStmt.getDate(3).value(), Date{2024y / April / 5d});
720721
BOOST_CHECK_EQUAL(selectStmt.getString(3).value(), "2024-04-05");
721722
BOOST_CHECK_EQUAL(selectStmt.getTime(4).value().to_duration(), Time{10h + 20min + 30s + 400000us}.to_duration());
722-
BOOST_CHECK_EQUAL(
723-
selectStmt.getTimestamp(5).value(), Timestamp{local_days{2024y / April / 5d} + 10h + 20min + 30s + 400000us});
723+
const Timestamp expectedTimestamp{Date{2024y / April / 5d}, Time{10h + 20min + 30s + 400000us}};
724+
BOOST_CHECK(selectStmt.getTimestamp(5).value() == expectedTimestamp);
724725
BOOST_CHECK_EQUAL(selectStmt.getTimeTz(6).value().zone, "UTC");
725726
BOOST_CHECK_EQUAL(selectStmt.getTimestampTz(7).value().zone, "UTC");
726727
}

0 commit comments

Comments
 (0)