Skip to content

Commit 3cacd83

Browse files
[ML] Encapsulate timestamp conversion from epoch seconds to epoch millis (#16)
1 parent 7f878cd commit 3cacd83

10 files changed

+42
-22
lines changed

include/core/CRapidJsonWriterBase.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <core/ImportExport.h>
1414
#include <core/CFunctional.h>
1515
#include <core/CRapidJsonPoolAllocator.h>
16+
#include <core/CTimeUtils.h>
1617

1718
#include <rapidjson/document.h>
1819
#include <rapidjson/stringbuffer.h>
@@ -183,6 +184,11 @@ class CRapidJsonWriterBase : public JSON_WRITER<OUTPUT_STREAM, SOURCE_ENCODING,
183184
return TRapidJsonWriterBase::Double(d);
184185
}
185186

187+
//! Writes an epoch second timestamp as an epoch millis timestamp
188+
bool Time(core_t::TTime t)
189+
{
190+
return this->Int64(CTimeUtils::toEpochMs(t));
191+
}
186192

187193
//! Push a constant string into a supplied rapidjson object value
188194
//! \p[in] value constant string
@@ -391,8 +397,7 @@ class CRapidJsonWriterBase : public JSON_WRITER<OUTPUT_STREAM, SOURCE_ENCODING,
391397
core_t::TTime value,
392398
TValue &obj) const
393399
{
394-
int64_t javaTimestamp = int64_t(value) * 1000;
395-
TValue v(javaTimestamp);
400+
TValue v(CTimeUtils::toEpochMs(value));
396401
this->addMember(fieldName, v, obj);
397402
}
398403

@@ -538,7 +543,7 @@ class CRapidJsonWriterBase : public JSON_WRITER<OUTPUT_STREAM, SOURCE_ENCODING,
538543

539544
for (const auto &value: values)
540545
{
541-
this->pushBack(value * int64_t(1000), array);
546+
this->pushBack(CTimeUtils::toEpochMs(value), array);
542547
}
543548

544549
this->addMember(fieldName, array, obj);

include/core/CTimeUtils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class CORE_EXPORT CTimeUtils : private CNonInstantiatable
5555
//! E.g. 19:20:30
5656
static std::string toTimeString(core_t::TTime t);
5757

58+
//! Converts an epoch seconds timestamp to epoch millis
59+
static int64_t toEpochMs(core_t::TTime t);
5860
//! strptime interface
5961
//! NOTE: the time returned here is a UTC value
6062
static bool strptime(const std::string &format,

lib/api/CJsonOutputWriter.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -491,7 +491,7 @@ void CJsonOutputWriter::writeBucket(bool isInterim,
491491
m_Writer.addIntFieldToObj(DETECTOR_INDEX, detectorIndex, *docPtr);
492492
m_Writer.addIntFieldToObj(BUCKET_SPAN, bucketData.s_BucketSpan, *docPtr);
493493
m_Writer.addStringFieldCopyToObj(JOB_ID, m_JobId, *docPtr);
494-
m_Writer.addIntFieldToObj(TIMESTAMP, bucketTime * 1000, *docPtr);
494+
m_Writer.addTimeFieldToObj(TIMESTAMP, bucketTime, *docPtr);
495495

496496
if (isInterim)
497497
{
@@ -522,7 +522,7 @@ void CJsonOutputWriter::writeBucket(bool isInterim,
522522
}
523523

524524
m_Writer.addStringFieldCopyToObj(JOB_ID, m_JobId, *docPtr);
525-
m_Writer.addIntFieldToObj(TIMESTAMP, bucketTime * 1000, *docPtr);
525+
m_Writer.addTimeFieldToObj(TIMESTAMP, bucketTime, *docPtr);
526526
if (isInterim)
527527
{
528528
m_Writer.addBoolFieldToObj(IS_INTERIM, isInterim, *docPtr);
@@ -542,7 +542,7 @@ void CJsonOutputWriter::writeBucket(bool isInterim,
542542
m_Writer.String(JOB_ID);
543543
m_Writer.String(m_JobId);
544544
m_Writer.String(TIMESTAMP);
545-
m_Writer.Int64(bucketTime * 1000);
545+
m_Writer.Time(bucketTime);
546546

547547
m_Writer.String(ANOMALY_SCORE);
548548
m_Writer.Double(bucketData.s_MaxBucketInfluencerNormalizedAnomalyScore);
@@ -577,7 +577,7 @@ void CJsonOutputWriter::writeBucket(bool isInterim,
577577

578578

579579
m_Writer.addStringFieldCopyToObj(JOB_ID, m_JobId, *docPtr);
580-
m_Writer.addIntFieldToObj(TIMESTAMP, bucketTime * 1000, *docPtr);
580+
m_Writer.addTimeFieldToObj(TIMESTAMP, bucketTime, *docPtr);
581581
m_Writer.addIntFieldToObj(BUCKET_SPAN, bucketData.s_BucketSpan, *docPtr);
582582
if (isInterim)
583583
{
@@ -975,7 +975,7 @@ void CJsonOutputWriter::acknowledgeFlush(const std::string &flushId, core_t::TTi
975975
m_Writer.String(ID);
976976
m_Writer.String(flushId);
977977
m_Writer.String(LAST_FINALIZED_BUCKET_END);
978-
m_Writer.Int64(lastFinalizedBucketEnd * 1000);
978+
m_Writer.Time(lastFinalizedBucketEnd);
979979

980980
m_Writer.EndObject();
981981
m_Writer.EndObject();

lib/api/CModelPlotDataJsonWriter.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ void CModelPlotDataJsonWriter::writeFlatRow(core_t::TTime time,
108108
m_Writer.addIntFieldToObj(DETECTOR_INDEX, detectorIndex, doc);
109109
m_Writer.addStringFieldCopyToObj(FEATURE, feature, doc, true);
110110
// time is in Java format - milliseconds since the epoch
111-
m_Writer.addIntFieldToObj(TIME, time * 1000, doc);
111+
m_Writer.addTimeFieldToObj(TIME, time, doc);
112112
m_Writer.addIntFieldToObj(BUCKET_SPAN, bucketSpan, doc);
113113
if (!partitionFieldName.empty())
114114
{

lib/api/CModelSizeStatsJsonWriter.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ void CModelSizeStatsJsonWriter::write(const std::string &jobId,
6666
writer.String(print(results.s_MemoryStatus));
6767

6868
writer.String(TIMESTAMP);
69-
writer.Int64(results.s_BucketStartTime * 1000);
69+
writer.Time(results.s_BucketStartTime);
7070

7171
writer.String(LOG_TIME);
72-
writer.Int64(core::CTimeUtils::now() * 1000);
72+
writer.Time(core::CTimeUtils::now());
7373

7474
writer.EndObject();
7575
}

lib/api/CModelSnapshotJsonWriter.cc

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,8 @@ void CModelSnapshotJsonWriter::write(const SModelSnapshotReport &report)
5151
m_Writer.String(SNAPSHOT_DOC_COUNT);
5252
m_Writer.Uint64(report.s_NumDocs);
5353

54-
// Write as a Java timestamp - ms since the epoch rather than seconds
55-
int64_t javaTimestamp = int64_t(report.s_SnapshotTimestamp) * 1000;
56-
5754
m_Writer.String(TIMESTAMP);
58-
m_Writer.Int64(javaTimestamp);
55+
m_Writer.Time(report.s_SnapshotTimestamp);
5956

6057
m_Writer.String(DESCRIPTION);
6158
m_Writer.String(report.s_Description);
@@ -64,17 +61,13 @@ void CModelSnapshotJsonWriter::write(const SModelSnapshotReport &report)
6461

6562
if (report.s_LatestRecordTime > 0)
6663
{
67-
javaTimestamp = int64_t(report.s_LatestRecordTime) * 1000;
68-
6964
m_Writer.String(LATEST_RECORD_TIME);
70-
m_Writer.Int64(javaTimestamp);
65+
m_Writer.Time(report.s_LatestRecordTime);
7166
}
7267
if (report.s_LatestFinalResultTime > 0)
7368
{
74-
javaTimestamp = int64_t(report.s_LatestFinalResultTime) * 1000;
75-
7669
m_Writer.String(LATEST_RESULT_TIME);
77-
m_Writer.Int64(javaTimestamp);
70+
m_Writer.Time(report.s_LatestFinalResultTime);
7871
}
7972

8073
// write normalizerState here
@@ -102,7 +95,7 @@ void CModelSnapshotJsonWriter::writeQuantileState(const std::string &jobId,
10295
writer.String(QUANTILE_STATE);
10396
writer.String(state);
10497
writer.String(TIMESTAMP);
105-
writer.Int64(time * 1000);
98+
writer.Time(time);
10699
writer.EndObject();
107100
}
108101

lib/core/CTimeUtils.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ std::string CTimeUtils::toTimeString(core_t::TTime t)
5252
return result;
5353
}
5454

55+
int64_t CTimeUtils::toEpochMs(core_t::TTime t)
56+
{
57+
return static_cast<int64_t>(t) * 1000;
58+
}
59+
5560
bool CTimeUtils::strptime(const std::string &format,
5661
const std::string &dateTime,
5762
core_t::TTime &preTime)

lib/core/unittest/CRapidJsonWriterBaseTest.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ const std::string NAN_NAME("nan");
4141
const std::string INFINITY_NAME("infinity");
4242
const std::string BOOL_NAME("bool");
4343
const std::string INT_NAME("int");
44+
const std::string TIME_NAME("time");
4445
const std::string UINT_NAME("uint");
4546
const std::string STR_ARRAY_NAME("str[]");
4647
const std::string DOUBLE_ARRAY_NAME("double[]");
@@ -66,6 +67,7 @@ void CRapidJsonWriterBaseTest::testAddFields(void)
6667
writer.addDoubleFieldToObj(INFINITY_NAME, std::numeric_limits<double>::infinity(), doc);
6768
writer.addBoolFieldToObj(BOOL_NAME, false, doc);
6869
writer.addIntFieldToObj(INT_NAME, -9, doc);
70+
writer.addTimeFieldToObj(TIME_NAME, ml::core_t::TTime(1521035866), doc);
6971
writer.addUIntFieldToObj(UINT_NAME, 999999999999999ull, doc);
7072
writer.addStringArrayFieldToObj(STR_ARRAY_NAME, TGenericLineWriter::TStrVec(3, "blah"), doc);
7173
writer.addDoubleArrayFieldToObj(DOUBLE_ARRAY_NAME, TGenericLineWriter::TDoubleVec(10, 1.5), doc);
@@ -88,6 +90,7 @@ void CRapidJsonWriterBaseTest::testAddFields(void)
8890
"\"infinity\":0,"
8991
"\"bool\":false,"
9092
"\"int\":-9,"
93+
"\"time\":1521035866000,"
9194
"\"uint\":999999999999999,"
9295
"\"str[]\":[\"blah\",\"blah\",\"blah\"],"
9396
"\"double[]\":[1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5,1.5],"

lib/core/unittest/CTimeUtilsTest.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ CppUnit::Test *CTimeUtilsTest::suite()
2727
suiteOfTests->addTest( new CppUnit::TestCaller<CTimeUtilsTest>(
2828
"CTimeUtilsTest::testToLocal",
2929
&CTimeUtilsTest::testToLocal) );
30+
suiteOfTests->addTest( new CppUnit::TestCaller<CTimeUtilsTest>(
31+
"CTimeUtilsTest::testToEpochMs",
32+
&CTimeUtilsTest::testToEpochMs) );
3033
suiteOfTests->addTest( new CppUnit::TestCaller<CTimeUtilsTest>(
3134
"CTimeUtilsTest::testStrptime",
3235
&CTimeUtilsTest::testStrptime) );
@@ -105,6 +108,14 @@ void CTimeUtilsTest::testToLocal(void)
105108
}
106109
}
107110

111+
void CTimeUtilsTest::testToEpochMs(void)
112+
{
113+
CPPUNIT_ASSERT_EQUAL(int64_t(1000), ml::core::CTimeUtils::toEpochMs(ml::core_t::TTime(1)));
114+
CPPUNIT_ASSERT_EQUAL(int64_t(-1000), ml::core::CTimeUtils::toEpochMs(ml::core_t::TTime(-1)));
115+
CPPUNIT_ASSERT_EQUAL(int64_t(1521035866000), ml::core::CTimeUtils::toEpochMs(ml::core_t::TTime(1521035866)));
116+
CPPUNIT_ASSERT_EQUAL(int64_t(-1521035866000), ml::core::CTimeUtils::toEpochMs(ml::core_t::TTime(-1521035866)));
117+
}
118+
108119
void CTimeUtilsTest::testStrptime(void)
109120
{
110121
// These tests assume UK time. In case they're ever run outside the UK,

lib/core/unittest/CTimeUtilsTest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class CTimeUtilsTest : public CppUnit::TestFixture
1515
void testNow(void);
1616
void testToIso8601(void);
1717
void testToLocal(void);
18+
void testToEpochMs(void);
1819
void testStrptime(void);
1920
void testTimezone(void);
2021
void testDateWords(void);

0 commit comments

Comments
 (0)