Skip to content

Commit

Permalink
Merge branch 'smalton/date-lib-enscapsulation' into 'master'
Browse files Browse the repository at this point in the history
Encapsulate `date` dependency

See merge request machine-learning/dorado!673
  • Loading branch information
malton-ont committed Nov 2, 2023
2 parents ac2a90a + 5857d94 commit 52cbabf
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 84 deletions.
2 changes: 0 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,6 @@ target_link_libraries(dorado_lib
htslib
vbz_hdf_plugin
edlib
date::date
dorado_utils
PRIVATE
${KOI_LIBRARIES}
Expand Down Expand Up @@ -465,7 +464,6 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL "iOS")
${POD5_LIBRARIES}
${HDF5_C_LIBRARIES}
${CMAKE_DL_LIBS}
date::date
)

if(WIN32)
Expand Down
33 changes: 2 additions & 31 deletions dorado/cli/summary.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@
#include "read_pipeline/HtsReader.h"
#include "utils/bam_utils.h"
#include "utils/log_utils.h"
#include "utils/time_utils.h"

#include <argparse.hpp>
#include <date/date.h>
#include <date/tz.h>
#include <spdlog/spdlog.h>

#include <cctype>
Expand All @@ -16,34 +15,6 @@ namespace dorado {

volatile sig_atomic_t interrupt = 0;

// todo: move to time_utils after !273
double time_difference_seconds(const std::string &timestamp1, const std::string &timestamp2) {
using namespace date;
using namespace std::chrono;
try {
std::istringstream ss1(timestamp1);
std::istringstream ss2(timestamp2);
sys_time<microseconds> time1, time2;
ss1 >> parse("%FT%T%Ez", time1);
ss2 >> parse("%FT%T%Ez", time2);
// If parsing with timezone offset failed, try parsing with 'Z' format
if (ss1.fail()) {
ss1.clear();
ss1.str(timestamp1);
ss1 >> parse("%FT%TZ", time1);
}
if (ss2.fail()) {
ss2.clear();
ss2.str(timestamp2);
ss2 >> parse("%FT%TZ", time2);
}
duration<double> diff = time1 - time2;
return diff.count();
} catch (const std::exception &e) {
throw std::runtime_error("Failed to parse timestamps");
}
}

int summary(int argc, char *argv[]) {
utils::InitLogging();

Expand Down Expand Up @@ -154,7 +125,7 @@ int summary(int argc, char *argv[]) {
float sample_rate = num_samples / duration;
float template_duration = (num_samples - trim_samples) / sample_rate;
auto exp_start_dt = read_group_exp_start_time.at(rg_value);
auto start_time = time_difference_seconds(start_time_dt, exp_start_dt);
auto start_time = utils::time_difference_seconds(start_time_dt, exp_start_dt);
auto template_start_time = start_time + (duration - template_duration);

std::cout << filename << separator << read_id << separator << run_id << separator << channel
Expand Down
3 changes: 2 additions & 1 deletion dorado/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ add_library(dorado_utils
stats.h
tensor_utils.cpp
tensor_utils.h
time_utils.cpp
time_utils.h
torch_utils.h
trim.cpp
Expand Down Expand Up @@ -85,11 +86,11 @@ target_link_libraries(dorado_utils
PUBLIC
${TORCH_LIBRARIES}
edlib
date::date
spdlog::spdlog
PRIVATE
minimap2
OpenSSL::SSL
date::date
htslib
)

Expand Down
91 changes: 91 additions & 0 deletions dorado/utils/time_utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#include "time_utils.h"

#include <date/date.h>
#include <date/tz.h>

#include <chrono>
#include <sstream>

namespace dorado::utils {

std::string get_string_timestamp_from_unix_time(time_t time_stamp_ms) {
auto tp = std::chrono::system_clock::from_time_t(time_stamp_ms / 1000);
tp += std::chrono::milliseconds(time_stamp_ms % 1000);
auto dp = date::floor<date::days>(tp);
auto time = date::make_time(std::chrono::duration_cast<std::chrono::milliseconds>(tp - dp));
auto ymd = date::year_month_day{dp};

std::ostringstream date_time_ss;
date_time_ss << ymd << "T" << time << "+00:00";
return date_time_ss.str();
}

// Expects the time to be encoded like "2017-09-12T09:50:12.456+00:00" or "2017-09-12T09:50:12Z".
// Time stamp can be specified up to microseconds
time_t get_unix_time_from_string_timestamp(const std::string & time_stamp) {
std::istringstream ss(time_stamp);
date::sys_time<std::chrono::microseconds> time_us;
ss >> date::parse("%FT%T%Ez", time_us);
// If parsing with timezone offset failed, try parsing with 'Z' format
if (ss.fail()) {
ss.clear();
ss.str(time_stamp);
ss >> date::parse("%FT%TZ", time_us);
}

auto epoch = time_us.time_since_epoch();
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
return value.count();
}

std::string adjust_time_ms(const std::string & time_stamp, uint64_t offset_ms) {
return get_string_timestamp_from_unix_time(get_unix_time_from_string_timestamp(time_stamp) +
offset_ms);
}

std::string adjust_time(const std::string & time_stamp, uint32_t offset) {
// Expects the time to be encoded like "2017-09-12T9:50:12Z".
// Adds the offset (in seconds) to the timeStamp.

date::sys_time<std::chrono::seconds> time_s;
std::istringstream ss(time_stamp);
ss >> date::parse("%FT%TZ", time_s);
time_s += std::chrono::seconds(offset);

auto dp = date::floor<date::days>(time_s);
auto time = date::make_time(time_s - dp);
auto ymd = date::year_month_day{dp};

std::ostringstream date_time_ss;
date_time_ss << ymd << "T" << time << "Z";
return date_time_ss.str();
}

double time_difference_seconds(const std::string & timestamp1, const std::string & timestamp2) {
using namespace date;
using namespace std::chrono;
try {
std::istringstream ss1(timestamp1);
std::istringstream ss2(timestamp2);
sys_time<microseconds> time1, time2;
ss1 >> parse("%FT%T%Ez", time1);
ss2 >> parse("%FT%T%Ez", time2);
// If parsing with timezone offset failed, try parsing with 'Z' format
if (ss1.fail()) {
ss1.clear();
ss1.str(timestamp1);
ss1 >> parse("%FT%TZ", time1);
}
if (ss2.fail()) {
ss2.clear();
ss2.str(timestamp2);
ss2 >> parse("%FT%TZ", time2);
}
duration<double> diff = time1 - time2;
return diff.count();
} catch (const std::exception & e) {
throw std::runtime_error("Failed to parse timestamps");
}
}

} // namespace dorado::utils
55 changes: 5 additions & 50 deletions dorado/utils/time_utils.h
Original file line number Diff line number Diff line change
@@ -1,65 +1,20 @@
#pragma once
#include <date/date.h>
#include <date/tz.h>

#include <chrono>
#include <ctime>
#include <sstream>
#include <string>

namespace dorado::utils {

inline std::string get_string_timestamp_from_unix_time(time_t time_stamp_ms) {
auto tp = std::chrono::system_clock::from_time_t(time_stamp_ms / 1000);
tp += std::chrono::milliseconds(time_stamp_ms % 1000);
auto dp = date::floor<date::days>(tp);
auto time = date::make_time(std::chrono::duration_cast<std::chrono::milliseconds>(tp - dp));
auto ymd = date::year_month_day{dp};

std::ostringstream date_time_ss;
date_time_ss << ymd << "T" << time << "+00:00";
return date_time_ss.str();
}
std::string get_string_timestamp_from_unix_time(time_t time_stamp_ms);

// Expects the time to be encoded like "2017-09-12T09:50:12.456+00:00" or "2017-09-12T09:50:12Z".
// Time stamp can be specified up to microseconds
inline time_t get_unix_time_from_string_timestamp(const std::string& time_stamp) {
std::istringstream ss(time_stamp);
date::sys_time<std::chrono::microseconds> time_us;
ss >> date::parse("%FT%T%Ez", time_us);
// If parsing with timezone offset failed, try parsing with 'Z' format
if (ss.fail()) {
ss.clear();
ss.str(time_stamp);
ss >> date::parse("%FT%TZ", time_us);
}

auto epoch = time_us.time_since_epoch();
auto value = std::chrono::duration_cast<std::chrono::milliseconds>(epoch);
return value.count();
}

inline std::string adjust_time_ms(const std::string& time_stamp, uint64_t offset_ms) {
return get_string_timestamp_from_unix_time(get_unix_time_from_string_timestamp(time_stamp) +
offset_ms);
}

inline std::string adjust_time(const std::string& time_stamp, uint32_t offset) {
// Expects the time to be encoded like "2017-09-12T9:50:12Z".
// Adds the offset (in seconds) to the timeStamp.
time_t get_unix_time_from_string_timestamp(const std::string& time_stamp);

date::sys_time<std::chrono::seconds> time_s;
std::istringstream ss(time_stamp);
ss >> date::parse("%FT%TZ", time_s);
time_s += std::chrono::seconds(offset);
std::string adjust_time_ms(const std::string& time_stamp, uint64_t offset_ms);

auto dp = date::floor<date::days>(time_s);
auto time = date::make_time(time_s - dp);
auto ymd = date::year_month_day{dp};
std::string adjust_time(const std::string& time_stamp, uint32_t offset);

std::ostringstream date_time_ss;
date_time_ss << ymd << "T" << time << "Z";
return date_time_ss.str();
}
double time_difference_seconds(const std::string& timestamp1, const std::string& timestamp2);

} // namespace dorado::utils

0 comments on commit 52cbabf

Please sign in to comment.