Skip to content

Commit

Permalink
Merge pull request #103 from simonkimi/add_timezone
Browse files Browse the repository at this point in the history
Add Time Zone and Daylight Saving Time Customization for MDF Data
  • Loading branch information
ihedvall committed Sep 11, 2024
2 parents b14d244 + 8414b6e commit 482bb14
Show file tree
Hide file tree
Showing 42 changed files with 1,400 additions and 116 deletions.
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

0 comments on commit 482bb14

Please sign in to comment.