Skip to content

Commit 69b60bd

Browse files
authored
Merge pull request #1 from Siderust/cout
Generic Time
2 parents 0e2390b + d7be04a commit 69b60bd

12 files changed

Lines changed: 527 additions & 378 deletions

File tree

.clang-format

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
Language: Cpp
3+
BasedOnStyle: LLVM
4+
IndentWidth: 2
5+
ColumnLimit: 80
6+
AllowShortBlocksOnASingleLine: Never
7+
AllowShortFunctionsOnASingleLine: All
8+
AllowShortEnumsOnASingleLine: true
9+
AllowShortIfStatementsOnASingleLine: Never
10+
AllowShortLoopsOnASingleLine: false
11+
AllowShortLambdasOnASingleLine: All
12+
AlwaysBreakTemplateDeclarations: MultiLine

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
[submodule "tempoch"]
22
path = tempoch
33
url = git@github.com:Siderust/tempoch.git
4+
[submodule "qtty-cpp"]
5+
path = qtty-cpp
6+
url = https://github.com/Siderust/qtty-cpp.git

CMakeLists.txt

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,17 @@ if(WIN32)
5959
endif()
6060
add_dependencies(tempoch_ffi build_tempoch_ffi)
6161

62+
# qtty-cpp integration (provides unit types for duration<>)
63+
add_subdirectory(qtty-cpp)
64+
6265
# Header-only C++ wrapper library
6366
add_library(tempoch_cpp INTERFACE)
6467
target_include_directories(tempoch_cpp INTERFACE
6568
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
6669
$<BUILD_INTERFACE:${TEMPOCH_FFI_INCLUDE_DIR}>
6770
$<INSTALL_INTERFACE:include>
6871
)
69-
target_link_libraries(tempoch_cpp INTERFACE tempoch_ffi)
72+
target_link_libraries(tempoch_cpp INTERFACE tempoch_ffi qtty_cpp)
7073
add_dependencies(tempoch_cpp build_tempoch_ffi)
7174

7275
# Doxygen documentation
@@ -77,13 +80,17 @@ if(TEMPOCH_BUILD_DOCS)
7780
set(TEMPOCH_DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.tempoch_cpp)
7881
configure_file(${TEMPOCH_DOXYFILE_IN} ${TEMPOCH_DOXYFILE_OUT} @ONLY)
7982

80-
add_custom_target(docs
81-
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/docs/doxygen
82-
COMMAND ${DOXYGEN_EXECUTABLE} ${TEMPOCH_DOXYFILE_OUT}
83-
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
84-
COMMENT "Generating API documentation with Doxygen"
85-
VERBATIM
86-
)
83+
if(NOT TARGET docs)
84+
add_custom_target(docs
85+
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/docs/doxygen
86+
COMMAND ${DOXYGEN_EXECUTABLE} ${TEMPOCH_DOXYFILE_OUT}
87+
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
88+
COMMENT "Generating API documentation with Doxygen"
89+
VERBATIM
90+
)
91+
else()
92+
message(STATUS "Top-level 'docs' target already exists; skipping creation to avoid conflict with subprojects")
93+
endif()
8794
else()
8895
message(STATUS "Doxygen not found; 'docs' target will not be available")
8996
endif()

examples/time_example.cpp

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,55 +8,62 @@
88
* ./build/time_example
99
*/
1010

11-
#include <tempoch/tempoch.hpp>
12-
#include <iostream>
1311
#include <iomanip>
12+
#include <iostream>
13+
#include <qtty/qtty.hpp>
14+
#include <tempoch/tempoch.hpp>
1415

1516
int main() {
16-
using namespace tempoch;
17-
18-
// ---------------------------------------------------------------
19-
// UTC → JulianDate → MJD round-trip
20-
// ---------------------------------------------------------------
21-
UTC utc(2026, 7, 15, 22, 0, 0);
22-
std::cout << "UTC: " << utc.year << "-"
23-
<< std::setfill('0') << std::setw(2) << (int)utc.month << "-"
24-
<< std::setw(2) << (int)utc.day << " "
25-
<< std::setw(2) << (int)utc.hour << ":"
26-
<< std::setw(2) << (int)utc.minute << ":"
27-
<< std::setw(2) << (int)utc.second << "\n";
28-
29-
auto jd = JulianDate::from_utc(utc);
30-
std::cout << "JD: " << std::fixed << std::setprecision(6) << jd.value() << "\n";
31-
32-
auto mjd = MJD::from_jd(jd);
33-
std::cout << "MJD: " << std::fixed << std::setprecision(6) << mjd.value() << "\n";
34-
35-
auto utc2 = mjd.to_utc();
36-
std::cout << "Back: " << utc2.year << "-"
37-
<< std::setfill('0') << std::setw(2) << (int)utc2.month << "-"
38-
<< std::setw(2) << (int)utc2.day << " "
39-
<< std::setw(2) << (int)utc2.hour << ":"
40-
<< std::setw(2) << (int)utc2.minute << ":"
41-
<< std::setw(2) << (int)utc2.second << "\n\n";
42-
43-
// ---------------------------------------------------------------
44-
// J2000 epoch and Julian centuries
45-
// ---------------------------------------------------------------
46-
auto j2000 = JulianDate::J2000();
47-
std::cout << "J2000.0: " << j2000.value() << "\n";
48-
std::cout << "Centuries since J2000: " << jd.julian_centuries() << "\n\n";
49-
50-
// ---------------------------------------------------------------
51-
// Period intersection
52-
// ---------------------------------------------------------------
53-
Period night(60200.0, 60200.5);
54-
Period obs(60200.2, 60200.8);
55-
auto overlap = night.intersection(obs);
56-
std::cout << "Night: [" << night.start_mjd() << ", " << night.end_mjd() << "]\n";
57-
std::cout << "Obs: [" << obs.start_mjd() << ", " << obs.end_mjd() << "]\n";
58-
std::cout << "Overlap: [" << overlap.start_mjd() << ", " << overlap.end_mjd() << "]\n";
59-
std::cout << "Overlap duration: " << overlap.duration_days() * 24.0 << " hours\n";
60-
61-
return 0;
17+
using namespace tempoch;
18+
19+
// ---------------------------------------------------------------
20+
// UTC → JulianDate → MJD round-trip
21+
// ---------------------------------------------------------------
22+
UTC utc(2026, 7, 15, 22, 0, 0);
23+
std::cout << "UTC: " << utc << "\n";
24+
25+
auto jd = JulianDate::from_utc(utc);
26+
std::cout << "JD: " << std::fixed << std::setprecision(6) << jd << "\n";
27+
28+
auto mjd = MJD::from_jd(jd);
29+
std::cout << "MJD: " << std::fixed << std::setprecision(6) << mjd << "\n";
30+
31+
auto utc2 = mjd.to_utc();
32+
std::cout << "Back: " << utc2 << "\n\n";
33+
34+
// ---------------------------------------------------------------
35+
// J2000 epoch and Julian centuries
36+
// ---------------------------------------------------------------
37+
auto j2000 = JulianDate::J2000();
38+
std::cout << "J2000.0: " << j2000 << "\n";
39+
std::cout << "Centuries since J2000: " << jd.julian_centuries() << "\n\n";
40+
41+
// ---------------------------------------------------------------
42+
// Period intersection (MJD — explicit MJD wrappers required)
43+
// ---------------------------------------------------------------
44+
Period night(MJD(60200.0), MJD(60200.5));
45+
Period obs(MJD(60200.2), MJD(60200.8));
46+
auto overlap = night.intersection(obs);
47+
std::cout << "Night: " << night << "\n";
48+
std::cout << "Obs: " << obs << "\n";
49+
std::cout << "Overlap: " << overlap << "\n";
50+
std::cout << "Overlap duration: " << overlap.duration<qtty::Hour>() << "\n\n";
51+
52+
// ---------------------------------------------------------------
53+
// Period<UTC> — start/end expressed directly as civil UTC
54+
// ---------------------------------------------------------------
55+
Period utc_semester(UTC(2026, 1, 1), UTC(2026, 7, 1));
56+
std::cout << "Semester (UTC): " << utc_semester << "\n";
57+
std::cout << " duration: " << utc_semester.duration() << "\n\n";
58+
59+
// ---------------------------------------------------------------
60+
// Period<JulianDate> — start/end as Julian Dates
61+
// ---------------------------------------------------------------
62+
auto jd_start = JulianDate::from_utc(UTC(2026, 1, 1));
63+
auto jd_end = JulianDate::from_utc(UTC(2026, 7, 1));
64+
Period jd_semester(jd_start, jd_end);
65+
std::cout << "Semester (JD): " << jd_semester << "\n";
66+
std::cout << " duration: " << jd_semester.duration() << "\n";
67+
68+
return 0;
6269
}

include/tempoch/ffi_core.hpp

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,39 +26,40 @@ namespace tempoch {
2626
*/
2727
class TempochException : public std::runtime_error {
2828
public:
29-
explicit TempochException(const std::string& msg) : std::runtime_error(msg) {}
29+
explicit TempochException(const std::string &msg) : std::runtime_error(msg) {}
3030
};
3131

3232
/**
3333
* @brief A required output pointer was null.
3434
*/
3535
class NullPointerError : public TempochException {
3636
public:
37-
explicit NullPointerError(const std::string& msg) : TempochException(msg) {}
37+
explicit NullPointerError(const std::string &msg) : TempochException(msg) {}
3838
};
3939

4040
/**
4141
* @brief UTC conversion failed (date out of range or invalid).
4242
*/
4343
class UtcConversionError : public TempochException {
4444
public:
45-
explicit UtcConversionError(const std::string& msg) : TempochException(msg) {}
45+
explicit UtcConversionError(const std::string &msg) : TempochException(msg) {}
4646
};
4747

4848
/**
4949
* @brief The period is invalid (start > end).
5050
*/
5151
class InvalidPeriodError : public TempochException {
5252
public:
53-
explicit InvalidPeriodError(const std::string& msg) : TempochException(msg) {}
53+
explicit InvalidPeriodError(const std::string &msg) : TempochException(msg) {}
5454
};
5555

5656
/**
5757
* @brief The two periods do not intersect.
5858
*/
5959
class NoIntersectionError : public TempochException {
6060
public:
61-
explicit NoIntersectionError(const std::string& msg) : TempochException(msg) {}
61+
explicit NoIntersectionError(const std::string &msg)
62+
: TempochException(msg) {}
6263
};
6364

6465
// ============================================================================
@@ -68,22 +69,24 @@ class NoIntersectionError : public TempochException {
6869
/**
6970
* @brief Check a tempoch_status_t and throw the appropriate exception on error.
7071
*/
71-
inline void check_status(tempoch_status_t status, const char* operation) {
72-
if (status == TEMPOCH_STATUS_T_OK) return;
72+
inline void check_status(tempoch_status_t status, const char *operation) {
73+
if (status == TEMPOCH_STATUS_T_OK)
74+
return;
7375

74-
std::string msg = std::string(operation) + " failed: ";
75-
switch (status) {
76-
case TEMPOCH_STATUS_T_NULL_POINTER:
77-
throw NullPointerError(msg + "null output pointer");
78-
case TEMPOCH_STATUS_T_UTC_CONVERSION_FAILED:
79-
throw UtcConversionError(msg + "UTC conversion failed");
80-
case TEMPOCH_STATUS_T_INVALID_PERIOD:
81-
throw InvalidPeriodError(msg + "invalid period (start > end)");
82-
case TEMPOCH_STATUS_T_NO_INTERSECTION:
83-
throw NoIntersectionError(msg + "periods do not intersect");
84-
default:
85-
throw TempochException(msg + "unknown error (" + std::to_string(status) + ")");
86-
}
76+
std::string msg = std::string(operation) + " failed: ";
77+
switch (status) {
78+
case TEMPOCH_STATUS_T_NULL_POINTER:
79+
throw NullPointerError(msg + "null output pointer");
80+
case TEMPOCH_STATUS_T_UTC_CONVERSION_FAILED:
81+
throw UtcConversionError(msg + "UTC conversion failed");
82+
case TEMPOCH_STATUS_T_INVALID_PERIOD:
83+
throw InvalidPeriodError(msg + "invalid period (start > end)");
84+
case TEMPOCH_STATUS_T_NO_INTERSECTION:
85+
throw NoIntersectionError(msg + "periods do not intersect");
86+
default:
87+
throw TempochException(msg + "unknown error (" + std::to_string(status) +
88+
")");
89+
}
8790
}
8891

8992
} // namespace tempoch

0 commit comments

Comments
 (0)