Skip to content

Commit 216a1d3

Browse files
authored
Merge pull request #356 from GeoscienceAustralia/dr-351
Report adjustment durations in HH:MM:SS for durations greater than 60s
2 parents 5746c7d + 8f7a8ed commit 216a1d3

9 files changed

Lines changed: 101 additions & 69 deletions

File tree

dynadjust/CMakeLists.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,13 @@ if (BUILD_TESTING)
942942
target_link_libraries(test_snx_file_writer PRIVATE ${DNA_LIBRARIES})
943943
target_compile_definitions(test_snx_file_writer PRIVATE __BINARY_NAME__="test_snx_file_writer" __BINARY_DESC__="Unit tests for SNX file writer")
944944

945+
# Test: test_format_elapsed_time
946+
add_executable(test_format_elapsed_time
947+
${UNIT_TEST_DIR}/test_format_elapsed_time.cpp
948+
)
949+
target_include_directories(test_format_elapsed_time PRIVATE ${UNIT_TEST_DIR} ${CMAKE_SOURCE_DIR}/include)
950+
target_compile_definitions(test_format_elapsed_time PRIVATE __BINARY_NAME__="test_format_elapsed_time" __BINARY_DESC__="Unit tests for FormatElapsedTime helper")
951+
945952
# Register unit tests with CTest
946953
add_test(NAME unit-MatrixTest COMMAND $<TARGET_FILE:test_matrix>)
947954
add_test(NAME unit-MsrToStnSortTest COMMAND $<TARGET_FILE:test_msr_to_stn_sort>)
@@ -957,6 +964,7 @@ if (BUILD_TESTING)
957964
add_test(NAME unit-AslFileLoaderTest COMMAND $<TARGET_FILE:test_asl_file_loader>)
958965
add_test(NAME unit-BmsFileLoaderTest COMMAND $<TARGET_FILE:test_bms_file_loader>)
959966
add_test(NAME unit-SnxFileWriterTest COMMAND $<TARGET_FILE:test_snx_file_writer>)
967+
add_test(NAME unit-FormatElapsedTimeTest COMMAND $<TARGET_FILE:test_format_elapsed_time>)
960968

961969
# ........................................................................
962970
# Functional tests
@@ -2026,7 +2034,7 @@ if (BUILD_TESTING)
20262034
unit-AmlFileLoaderTest unit-BmsFileTest unit-NetworkDataLoaderTest
20272035
unit-MeasurementProcessorTest unit-DynAdjustPrinterTest unit-GNSSNstatSortTest
20282036
unit-BstFileLoaderTest unit-AslFileLoaderTest unit-BmsFileLoaderTest
2029-
unit-SnxFileWriterTest
2037+
unit-SnxFileWriterTest unit-FormatElapsedTimeTest
20302038
)
20312039
set_tests_properties(${UNIT_TESTS} PROPERTIES
20322040
RUN_SERIAL FALSE

dynadjust/dynadjust/dnaadjust/dnaadjust-multi.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ void dna_adjust::AdjustPhasedMultiThread()
192192
if (IsCancelled())
193193
break;
194194

195-
std::string iteration_time_str = format_wall_time(it_time.elapsed().wall);
195+
std::string iteration_time_str = FormatElapsedTime(it_time.elapsed().wall.count() / 1.0e9);
196196

197197
///////////////////////////////////
198198
// protected write to adj file (not needed here since write to

dynadjust/dynadjust/dnaadjust/dnaadjust.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2433,7 +2433,7 @@ void dna_adjust::AdjustSimultaneous()
24332433

24342434
// update data for messages
24352435
iterationCorrections_.add_message(corr_msg);
2436-
iterationTimes_.add_message(format_wall_time(it_time.elapsed().wall));
2436+
iterationTimes_.add_message(FormatElapsedTime(it_time.elapsed().wall.count() / 1.0e9));
24372437
iterationQueue_.push_and_notify(CurrentIteration()); // currentIteration begins at 1, so not zero-indexed
24382438
isIterationComplete_ = true;
24392439

@@ -2571,7 +2571,7 @@ void dna_adjust::AdjustPhased()
25712571
OutputLargestCorrection(corr_msg);
25722572

25732573
iterationCorrections_.add_message(corr_msg);
2574-
iterationTimes_.add_message(format_wall_time(it_time.elapsed().wall));
2574+
iterationTimes_.add_message(FormatElapsedTime(it_time.elapsed().wall.count() / 1.0e9));
25752575
iterationQueue_.push_and_notify(CurrentIteration()); // currentIteration begins at 1, so not zero-indexed
25762576
isIterationComplete_ = true;
25772577

@@ -2650,7 +2650,7 @@ void dna_adjust::AdjustPhasedBlock1()
26502650
adjustStatus_ = ADJUST_THRESHOLD_EXCEEDED;
26512651

26522652
iterationCorrections_.add_message(corr_msg);
2653-
iterationTimes_.add_message(format_wall_time(it_time.elapsed().wall));
2653+
iterationTimes_.add_message(FormatElapsedTime(it_time.elapsed().wall.count() / 1.0e9));
26542654
iterationQueue_.push_and_notify(CurrentIteration()); // currentIteration begins at 1, so not zero-indexed
26552655

26562656
ValidateandFinaliseAdjustment(tot_time);

dynadjust/dynadjust/dnaadjust/dnaadjust.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ namespace networkadjust {
102102
extern std::mutex maxCorrMutex;
103103

104104
using dynadjust::cpu_timer;
105-
using dynadjust::format_wall_time;
105+
using dynadjust::FormatElapsedTime;
106106

107107
// forward declaration of dna_adjust
108108
class dna_adjust;

dynadjust/dynadjust/dnaadjust/dnaadjust_printer.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,13 @@ void DynAdjustPrinter::PrintIteration(const UINT32& iteration) {
8080
}
8181

8282
void DynAdjustPrinter::PrintAdjustmentTime(cpu_timer& time, int timer_type) {
83-
std::string time_str = format_wall_time(time.elapsed().wall);
83+
std::string formatted = FormatElapsedTime(time.elapsed().wall.count() / 1.0e9);
8484

8585
if (timer_type == 0) // iteration_time equivalent
86-
adjust_.adj_file << std::setw(PRINT_VAR_PAD) << std::left << "Elapsed time" << time_str << std::endl;
86+
adjust_.adj_file << std::setw(PRINT_VAR_PAD) << std::left << "Elapsed time" << formatted << std::endl;
8787
else
8888
{
89-
adjust_.adj_file << std::setw(PRINT_VAR_PAD) << std::left << "Total time" << time_str << std::endl << std::endl;
89+
adjust_.adj_file << std::setw(PRINT_VAR_PAD) << std::left << "Total time" << formatted << std::endl << std::endl;
9090
}
9191
}
9292

dynadjust/include/functions/dnatemplatedatetimefuncs.hpp

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
#include <include/functions/dnastrmanipfuncs.hpp>
3939
#include <include/functions/dnastrutils.hpp>
40+
#include <include/functions/dnatimer.hpp>
4041

4142
const UINT32 TIME_IMMEMORIAL = 1900;
4243

@@ -562,39 +563,8 @@ T formattedDateTimeString()
562563
template <typename S>
563564
S formatedElapsedTime(boost::posix_time::milliseconds* elapsed_time, S app_message)
564565
{
565-
std::ostringstream ss_time;
566-
boost::posix_time::ptime pt(boost::posix_time::ptime(boost::gregorian::day_clock::local_day(), *elapsed_time));
567-
568-
if (*elapsed_time < boost::posix_time::seconds(3))
569-
{
570-
boost::posix_time::time_facet* facet(new boost::posix_time::time_facet("%s"));
571-
ss_time.imbue(std::locale(ss_time.getloc(), facet));
572-
ss_time.str("");
573-
ss_time << pt << "s";
574-
}
575-
else if (*elapsed_time < boost::posix_time::seconds(61))
576-
{
577-
boost::posix_time::time_facet* facet(new boost::posix_time::time_facet("%S"));
578-
ss_time.imbue(std::locale(ss_time.getloc(), facet));
579-
ss_time.str("");
580-
ss_time << pt << "s";
581-
}
582-
else
583-
ss_time << boost::posix_time::seconds(static_cast<long>(elapsed_time->total_seconds()));
584-
585-
size_t pos = std::string::npos;
586-
std::string time_message = ss_time.str();
587-
while ((pos = time_message.find("0s")) != std::string::npos)
588-
time_message = time_message.substr(0, pos) + "s";
589-
590-
time_message = app_message + time_message + ".";
591-
592-
if ((pos = time_message.find(" 00.")) != std::string::npos)
593-
time_message = time_message.replace(pos, 4, " 0.");
594-
if ((pos = time_message.find(" 0.s")) != std::string::npos)
595-
time_message = time_message.replace(pos, 4, " 0s");
596-
597-
return time_message;
566+
double seconds = static_cast<double>(elapsed_time->total_milliseconds()) / 1000.0;
567+
return app_message + dynadjust::FormatElapsedTime(seconds) + ".";
598568
}
599569

600570

dynadjust/include/functions/dnatimer.hpp

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
// Licensed under the Apache License, Version 2.0 (the "License");
88
// you may not use this file except in compliance with the License.
99
// You may obtain a copy of the License at
10-
//
10+
//
1111
// http ://www.apache.org/licenses/LICENSE-2.0
12-
//
12+
//
1313
// Unless required by applicable law or agreed to in writing, software
1414
// distributed under the License is distributed on an "AS IS" BASIS,
1515
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -23,65 +23,72 @@
2323
#define DNATIMER_H_
2424

2525
#include <chrono>
26-
#include <string>
27-
#include <sstream>
2826
#include <iomanip>
27+
#include <sstream>
28+
#include <string>
2929

3030
namespace dynadjust {
3131

3232
// High-precision timer class to replace boost::timer::cpu_timer
3333
class cpu_timer {
34-
public:
34+
public:
3535
struct cpu_times {
3636
std::chrono::nanoseconds wall;
3737
std::chrono::nanoseconds user;
3838
std::chrono::nanoseconds system;
3939
};
4040

4141
cpu_timer() { start(); }
42-
43-
void start() {
44-
start_time_ = std::chrono::high_resolution_clock::now();
45-
}
46-
47-
void resume() {
48-
start();
49-
}
50-
42+
43+
void start() { start_time_ = std::chrono::high_resolution_clock::now(); }
44+
45+
void resume() { start(); }
46+
5147
void stop() {
5248
// For compatibility, but no-op since we calculate elapsed on demand
5349
}
54-
50+
5551
cpu_times elapsed() const {
5652
auto end_time = std::chrono::high_resolution_clock::now();
5753
auto wall_duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time_);
58-
return {wall_duration, wall_duration, wall_duration}; // For simplicity, user and system = wall
54+
return {wall_duration, wall_duration, wall_duration}; // For simplicity, user and system = wall
5955
}
60-
56+
6157
std::string format(int places = 6) const {
6258
auto times = elapsed();
6359
double wall_seconds = times.wall.count() / 1e9;
64-
60+
6561
std::ostringstream oss;
6662
oss << std::fixed << std::setprecision(places);
6763
oss << wall_seconds << "s wall";
6864
return oss.str();
6965
}
7066

71-
private:
67+
private:
7268
std::chrono::high_resolution_clock::time_point start_time_;
7369
};
7470

75-
inline std::string format_wall_time(std::chrono::nanoseconds wall) {
76-
double seconds = wall.count() / 1.0e9;
71+
// Format an elapsed duration (in seconds) for display.
72+
// < 1 second -> "X.XXXms"
73+
// 1..60 second -> "X.XXXs"
74+
// >= 60 second -> "hh:mm:ss"
75+
inline std::string FormatElapsedTime(double seconds) {
7776
std::ostringstream oss;
78-
if (seconds >= 1.0)
79-
oss << std::fixed << std::setprecision(3) << seconds << "s";
80-
else
77+
if (seconds >= 60.0) {
78+
long total_seconds = static_cast<long>(seconds);
79+
long hours = total_seconds / 3600;
80+
long minutes = (total_seconds % 3600) / 60;
81+
long secs = total_seconds % 60;
82+
oss << std::setfill('0') << std::setw(2) << hours << ':' << std::setw(2) << minutes << ':' << std::setw(2)
83+
<< secs;
84+
} else if (seconds >= 1.0) {
85+
oss << std::fixed << std::setprecision(3) << seconds << 's';
86+
} else {
8187
oss << std::fixed << std::setprecision(3) << (seconds * 1000.0) << "ms";
88+
}
8289
return oss.str();
8390
}
8491

8592
} // namespace dynadjust
8693

87-
#endif // DNATIMER_H_
94+
#endif // DNATIMER_H_

tests/CMakeLists.txt

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,16 @@ target_compile_definitions(test_gnss_nstat_sort PRIVATE
219219
__BINARY_DESC__="Unit tests for GNSS n-stat sort in alternate units"
220220
)
221221

222+
# Test 11: FormatElapsedTime helper (issue #351)
223+
add_executable(test_format_elapsed_time
224+
test_format_elapsed_time.cpp
225+
)
226+
227+
target_compile_definitions(test_format_elapsed_time PRIVATE
228+
__BINARY_NAME__="test_format_elapsed_time"
229+
__BINARY_DESC__="Unit tests for FormatElapsedTime helper (issue #351)"
230+
)
231+
222232
# Enable testing
223233
enable_testing()
224234

@@ -233,16 +243,17 @@ add_test(NAME NetworkDataLoaderTest COMMAND test_network_data_loader)
233243
add_test(NAME MeasurementProcessorTest COMMAND test_measurement_processor)
234244
add_test(NAME DynAdjustPrinterTest COMMAND test_dnaadjust_printer)
235245
add_test(NAME GNSSNstatSortTest COMMAND test_gnss_nstat_sort)
246+
add_test(NAME FormatElapsedTimeTest COMMAND test_format_elapsed_time)
236247

237248
# Custom target to run all tests
238249
add_custom_target(run_tests
239250
COMMAND ${CMAKE_CTEST_COMMAND} --verbose
240-
DEPENDS test_matrix test_msr_to_stn_sort test_bst_file test_asl_file test_aml_file_loader test_bms_file test_network_data_loader test_measurement_processor test_dnaadjust_printer test_gnss_nstat_sort
251+
DEPENDS test_matrix test_msr_to_stn_sort test_bst_file test_asl_file test_aml_file_loader test_bms_file test_network_data_loader test_measurement_processor test_dnaadjust_printer test_gnss_nstat_sort test_format_elapsed_time
241252
COMMENT "Running all tests"
242253
)
243254

244255
# Custom target equivalent to 'make all'
245256
add_custom_target(tests_all
246-
DEPENDS test_matrix test_msr_to_stn_sort test_bst_file test_asl_file test_aml_file_loader test_bms_file test_network_data_loader test_measurement_processor test_dnaadjust_printer test_gnss_nstat_sort
257+
DEPENDS test_matrix test_msr_to_stn_sort test_bst_file test_asl_file test_aml_file_loader test_bms_file test_network_data_loader test_measurement_processor test_dnaadjust_printer test_gnss_nstat_sort test_format_elapsed_time
247258
COMMENT "Building all tests"
248259
)

tests/test_format_elapsed_time.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#define TESTING_MAIN
2+
#ifndef __BINARY_NAME__
3+
#define __BINARY_NAME__ "test_format_elapsed_time"
4+
#endif
5+
#ifndef __BINARY_DESC__
6+
#define __BINARY_DESC__ "Unit tests for FormatElapsedTime helper (issue #351)"
7+
#endif
8+
9+
#include "testing.hpp"
10+
11+
#include "../dynadjust/include/functions/dnatimer.hpp"
12+
13+
using dynadjust::FormatElapsedTime;
14+
15+
TEST_CASE("Sub-second durations report milliseconds", "[time][issue351]") {
16+
REQUIRE(FormatElapsedTime(0.000078) == "0.078ms");
17+
REQUIRE(FormatElapsedTime(0.0) == "0.000ms");
18+
REQUIRE(FormatElapsedTime(0.5) == "500.000ms");
19+
REQUIRE(FormatElapsedTime(0.999) == "999.000ms");
20+
}
21+
22+
TEST_CASE("Durations between 1 and 60 seconds report seconds", "[time][issue351]") {
23+
REQUIRE(FormatElapsedTime(1.0) == "1.000s");
24+
REQUIRE(FormatElapsedTime(12.580) == "12.580s");
25+
REQUIRE(FormatElapsedTime(59.999) == "59.999s");
26+
}
27+
28+
TEST_CASE("Durations of 60 seconds or more report hh:mm:ss", "[time][issue351]") {
29+
REQUIRE(FormatElapsedTime(60.0) == "00:01:00");
30+
REQUIRE(FormatElapsedTime(68.0) == "00:01:08");
31+
REQUIRE(FormatElapsedTime(139.419) == "00:02:19");
32+
REQUIRE(FormatElapsedTime(3600.0) == "01:00:00");
33+
REQUIRE(FormatElapsedTime(5841.0) == "01:37:21");
34+
REQUIRE(FormatElapsedTime(26697.777) == "07:24:57");
35+
REQUIRE(FormatElapsedTime(36000.0) == "10:00:00");
36+
}

0 commit comments

Comments
 (0)