Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Time Zone and Daylight Saving Time Customization for MDF Data #103

Merged
merged 11 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion include/mdf/ifilehistory.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
#include <cstdint>
#include <string>

#include "mdf/imetadata.h"
#include "imdftimestamp.h"
#include "itimestamp.h"
#include "mdf/iblock.h"
#include "mdf/imetadata.h"

namespace mdf {

Expand All @@ -33,12 +35,30 @@ class IFileHistory : public IBlock {
*/
virtual void Time(uint64_t ns_since_1970) = 0;

/**
* \brief Sets the time using an ITimestamp object.
*
* This function sets the time for the history block using an ITimestamp
* object.
* @param timestamp An ITimestamp object representing the time.
*/
virtual void Time(ITimestamp& timestamp) = 0;

/** \brief Returns the time for the history block.
*
* Sets the time the history block was created.
* @return Nanoseconds since 1970.
*/
[[nodiscard]] virtual uint64_t Time() const = 0;

/** \brief Returns the start timestamp of the measurement.
*
* This function returns the start timestamp of the measurement as a pointer
* to an IMdfTimestamp object.
* @return Pointer to an IMdfTimestamp object representing the start
* timestamp.
*/
[[nodiscard]] virtual const mdf::IMdfTimestamp* StartTimestamp() const = 0;

/** \brief Returns an interface against a MD4 block
*
Expand Down
19 changes: 19 additions & 0 deletions include/mdf/iheader.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include <string>
#include <vector>
#include "mdf/iblock.h"
#include "itimestamp.h"
#include "imdftimestamp.h"

namespace mdf {

Expand Down Expand Up @@ -152,13 +154,30 @@ class IHeader : public IBlock {
*/
virtual void StartTime(uint64_t ns_since_1970) = 0;

/** \brief Sets the absolute measurement time for the file.
*
* Sets the absolute start time for the measurement file using an ITimestamp
* object.
* @param timestamp An ITimestamp object representing the start time.
*/
virtual void StartTime(ITimestamp& timestamp) = 0;

/** \brief Returns the absolute measurement time for the file.
*
* Returns the absolute start time for the measurement file.
* @return Nanoseconds since 1970.
*/
[[nodiscard]] virtual uint64_t StartTime() const = 0;

/** \brief Returns the start timestamp of the measurement.
*
* This function returns the start timestamp of the measurement as a pointer
* to an IMdfTimestamp object.
* @return Pointer to an IMdfTimestamp object representing the start
* timestamp.
*/
[[nodiscard]] virtual const IMdfTimestamp* StartTimestamp() const = 0;

/** \brief Returns meta data information object.
*
* Returns meta data as a text string typically as an XML snippets.
Expand Down
55 changes: 55 additions & 0 deletions include/mdf/imdftimestamp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#pragma once

#include "mdf/itimestamp.h"

namespace mdf {

namespace timetype
{
enum MdfTimestampType {
kUtcTime, /**< Represents the UTC time. */
kLocalTime, /**< Represents the local time. */
kLocalTimeTz, /**< Represents the local time with timezone offset. */
kTimezoneTime /**< Represents the time with timezone offset. */
};
}

class ITimestamp;

/**
* \brief Interface for MDF timestamp handling.
*/
class IMdfTimestamp {
public:
/**
* \brief Set the time in nanoseconds.
* \param time The time in nanoseconds.
*/
virtual void SetTime(uint64_t time) = 0;
/**
* \brief Set the time using an ITimestamp object.
* \param timestamp An ITimestamp object representing the time.
*/
virtual void SetTime(ITimestamp &timestamp) = 0;
/**
* \brief Get the time in nanoseconds.
* \return The time in nanoseconds.
*/
[[nodiscard]] virtual uint64_t GetTimeNs() const = 0;
/**
* \brief Get the timezone offset in minutes.
* \return The timezone offset in minutes.
*/
[[nodiscard]] virtual uint16_t GetTzOffsetMin() const = 0;
/**
* \brief Get the daylight saving time offset in minutes.
* \return The daylight saving time offset in minutes.
*/
[[nodiscard]] virtual uint16_t GetDstOffsetMin() const = 0;
/**
* \brief Get the type of MDF timestamp.
* \return The MDF timestamp type.
*/
[[nodiscard]] virtual timetype::MdfTimestampType GetTimeType() const = 0;
};
} // namespace mdf
111 changes: 111 additions & 0 deletions include/mdf/itimestamp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#pragma once
#include <string>

namespace mdf {

namespace timeunits {
constexpr uint64_t kNanosecondsPerSecond = 1'000'000'000;
constexpr uint64_t kNanosecondsPerMinute = 60 * kNanosecondsPerSecond;
constexpr uint64_t kNanosecondsPerHour = 60 * kNanosecondsPerMinute;
constexpr uint32_t kSecondsPerMinute = 60;
constexpr uint32_t kSecondsPerHour = 60 * kSecondsPerMinute;
} // namespace timeunits

/**
* \brief Interface for timestamp handling in MDF files.
*/
class ITimestamp {
public:
/**
* \brief Virtual destructor for ITimestamp.
*/
virtual ~ITimestamp() = default;
/**
* \brief Get the time in nanoseconds.
* \return Time in nanoseconds.
*/
[[nodiscard]] virtual uint64_t GetTimeNs() const = 0;
/**
* \brief Get the timezone offset in minutes.
* \return Timezone offset in minutes.
*/
[[nodiscard]] virtual int16_t GetTimezoneMin() const = 0;
/**
* \brief Get the daylight saving time offset in minutes.
* \return DST offset in minutes.
*/
[[nodiscard]] virtual int16_t GetDstMin() const = 0;
/**
* \brief Get the UTC time in nanoseconds.
* \return UTC time in nanoseconds.
*/
[[nodiscard]] virtual uint64_t GetUtcTimeNs() const = 0;
};

/**
* \brief Class representing a UTC timestamp.
*/
class UtcTimestamp : public ITimestamp {
public:
/**
* \brief Constructor for UtcTimeStamp.
* \param utc_timestamp The UTC timestamp in nanoseconds.
*/
explicit UtcTimestamp(uint64_t utc_timestamp);

[[nodiscard]] uint64_t GetTimeNs() const override;
[[nodiscard]] int16_t GetTimezoneMin() const override;
[[nodiscard]] int16_t GetDstMin() const override;
[[nodiscard]] uint64_t GetUtcTimeNs() const override;

private:
uint64_t utc_timestamp_; ///< The UTC timestamp in nanoseconds.
};

/**
* \brief Class representing a local timestamp, with timezone and DST offset.
*/
class LocalTimestamp : public ITimestamp {
public:
/**
* \brief Constructor for LocalTimeStamp.
* \param local_timestamp The local timestamp in nanoseconds, with timezone
* and DST offset.
*/
explicit LocalTimestamp(uint64_t local_timestamp);
[[nodiscard]] uint64_t GetTimeNs() const override;
[[nodiscard]] int16_t GetTimezoneMin() const override;
[[nodiscard]] int16_t GetDstMin() const override;
[[nodiscard]] uint64_t GetUtcTimeNs() const override;

private:
uint64_t local_timestamp_; ///< The local timestamp in nanoseconds, with
///< timezone and DST offset.
int16_t timezone_offset_min_ = 0; ///< The timezone offset in minutes.
int16_t dst_offset_min_ = 0; ///< The daylight saving time offset in minutes.
};

/**
* \brief Class representing a timestamp with timezone information.
*/
class TimezoneTimestamp : public ITimestamp {
public:
/**
* \brief Constructor for TimezoneTimeStamp.
* \param utc_timestamp The UTC timestamp in nanoseconds.
* \param timezone_offset_min The timezone offset in minutes.
* \param dst_offset_min The daylight saving time offset in minutes.
*/
TimezoneTimestamp(uint64_t utc_timestamp, int16_t timezone_offset_min,
int16_t dst_offset_min);
[[nodiscard]] uint64_t GetTimeNs() const override;
[[nodiscard]] int16_t GetTimezoneMin() const override;
[[nodiscard]] int16_t GetDstMin() const override;
[[nodiscard]] uint64_t GetUtcTimeNs() const override;

private:
uint64_t utc_timestamp_; ///< The UTC timestamp in nanoseconds.
int16_t timezone_offset_min_; ///< The timezone offset in minutes.
int16_t dst_offset_min_; ///< The daylight saving time offset in minutes.
};
} // namespace mdf
71 changes: 70 additions & 1 deletion include/mdf/mdfhelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class MdfHelper {
public:
/** \brief Adds the time zone offset to the time stamp.
*
* Adds the time zone offset to the UTC nanoseconds since 1970.
* Adds the time zone offset and dst to the UTC nanoseconds since 1970.
* @param [in] ns_since_1970 Nano-seconds since 1970
* @return local time = system time + time zone offset
*/
Expand All @@ -29,6 +29,23 @@ class MdfHelper {
*/
static int64_t TimeZoneOffset();

/**
* \brief Returns the GMT offset in nanoseconds.
*
* This function returns the current GMT offset in nanoseconds.
* @return GMT offset in nanoseconds.
*/
static int64_t GmtOffsetNs();

/**
* \brief Returns the daylight saving time (DST) offset in nanoseconds.
*
* This function returns the current daylight saving time (DST) offset in
* nanoseconds.
* @return DST offset in nanoseconds.
*/
static int64_t DstOffsetNs();

/** \brief Converts a nanosecond since 1970 to a local ISO date and time
* string.
*
Expand Down Expand Up @@ -124,6 +141,58 @@ class MdfHelper {
* @return Local date format 'HH:MM:SS'
*/
static std::string NanoSecToHHMMSS(uint64_t ns_since_1970);

/** \brief Converts ns since 1970 UTC to UTC time in 'HH:MM:SS' format.
*
* Generates a UTC time string in the 'HH:MM:SS' format from a timestamp
* representing nanoseconds since 1970-01-01 (midnight) UTC. This is useful for
* converting a high-precision timestamp to a human-readable time format in UTC.
*
* @param [in] timestamp_ns Nanoseconds since 1970 UTC.
* @return UTC time format 'HH:MM:SS'.
*/
static std::string NanoSecUtcToHHMMSS(uint64_t timestamp_ns);

/** \brief Converts ns since 1970 UTC to UTC date in 'DD/MM/YYYY' format.
*
* Generates a UTC date string in the 'DD/MM/YYYY' format from a timestamp
* representing nanoseconds since 1970-01-01 (midnight) UTC. This function is
* useful for converting a high-precision timestamp into a human-readable date in UTC.
*
* @param [in] timestamp_ns Nanoseconds since 1970 UTC.
* @return UTC date format 'DD/MM/YYYY'.
*/
static std::string NanoSecUtcToDDMMYYYY(uint64_t timestamp_ns);

/** \brief Converts ns since 1970 UTC to a time string in 'HH:MM:SS' format in a specified timezone.
*
* Generates a time string in the 'HH:MM:SS' format based on a timestamp
* representing nanoseconds since 1970-01-01 (midnight) UTC, adjusted for a
* specified timezone and daylight saving time (DST) offset. This function
* is useful for converting a high-precision timestamp into a human-readable
* time in a specific timezone.
*
* @param [in] timestamp_ns Nanoseconds since 1970 UTC.
* @param [in] tz_offset_min Timezone offset in minutes from UTC.
* @param [in] dst_offset_min Daylight saving time (DST) offset in minutes.
* @return Time format 'HH:MM:SS' adjusted for the specified timezone and DST offset.
*/
static std::string NanoSecTzToHHMMSS(uint64_t timestamp_ns, int16_t tz_offset_min, int16_t dst_offset_min);

/** \brief Converts ns since 1970 UTC to a date string in 'DD/MM/YYYY' format in a specified timezone.
*
* Generates a date string in the 'DD/MM/YYYY' format based on a timestamp
* representing nanoseconds since 1970-01-01 (midnight) UTC, adjusted for a
* specified timezone and daylight saving time (DST) offset. This function
* is useful for converting a high-precision timestamp into a human-readable
* date in a specific timezone.
*
* @param [in] timestamp_ns Nanoseconds since 1970 UTC.
* @param [in] tz_offset_min Timezone offset in minutes from UTC.
* @param [in] dst_offset_min Daylight saving time (DST) offset in minutes.
* @return Date format 'DD/MM/YYYY' adjusted for the specified timezone and DST offset.
*/
static std::string NanoSecTzToDDMMYYYY(uint64_t timestamp_ns, int16_t tz_offset_min, int16_t dst_offset_min);

/** \brief Remove white space from string.
*
Expand Down
6 changes: 6 additions & 0 deletions include/mdf/mdfwriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,14 @@ class MdfWriter {

/** \brief Starts the measurement. */
virtual void StartMeasurement(uint64_t start_time);

/** \brief Starts the measurement. */
virtual void StartMeasurement(ITimestamp &start_time);
/** \brief Stops the measurement. */
virtual void StopMeasurement(uint64_t stop_time);
/** \brief Stops the measurement. */
virtual void StopMeasurement(ITimestamp &start_time);

/** \brief Stop the sample queue and write all unwritten blocks to
* the file.*/
virtual bool FinalizeMeasurement();
Expand Down
5 changes: 5 additions & 0 deletions mdflib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ add_library(mdf
src/cgrange.h
src/mdfconverter.cpp
src/mdfconverter.h
src/timestamp.cpp
../include/mdf/imdftimestamp.h
src/timestamp.cpp
src/mdf3timestamp.cpp
src/mdf3timestamp.h
)

set(CMAKE_POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS})
Expand Down
3 changes: 3 additions & 0 deletions mdflib/mdflib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@
<ClCompile Include="src\littlebuffer.cpp" />
<ClCompile Include="src\md4block.cpp" />
<ClCompile Include="src\mdf3file.cpp" />
<ClCompile Include="src\mdf3timestamp.cpp" />
<ClCompile Include="src\mdf3writer.cpp" />
<ClCompile Include="src\mdf4file.cpp" />
<ClCompile Include="src\mdf4timestamp.cpp" />
Expand All @@ -266,6 +267,7 @@
<ClCompile Include="src\si4block.cpp" />
<ClCompile Include="src\sr3block.cpp" />
<ClCompile Include="src\sr4block.cpp" />
<ClCompile Include="src\timestamp.cpp" />
<ClCompile Include="src\tr3block.cpp" />
<ClCompile Include="src\tx3block.cpp" />
<ClCompile Include="src\tx4block.cpp" />
Expand Down Expand Up @@ -343,6 +345,7 @@
<ClInclude Include="src\littlebuffer.h" />
<ClInclude Include="src\md4block.h" />
<ClInclude Include="src\mdf3file.h" />
<ClInclude Include="src\mdf3timestamp.h" />
<ClInclude Include="src\mdf3writer.h" />
<ClInclude Include="src\mdf4file.h" />
<ClInclude Include="src\mdf4timestamp.h" />
Expand Down
Loading
Loading