Skip to content

Commit 69bfb0c

Browse files
[ML] Encapsulate timestamp conversion from epoch seconds to epoch millis (#16)
1 parent 6f42c0f commit 69bfb0c

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
@@ -22,6 +22,7 @@
2222
#include <core/ImportExport.h>
2323
#include <core/CFunctional.h>
2424
#include <core/CRapidJsonPoolAllocator.h>
25+
#include <core/CTimeUtils.h>
2526

2627
#include <rapidjson/document.h>
2728
#include <rapidjson/stringbuffer.h>
@@ -197,6 +198,11 @@ class CRapidJsonWriterBase : public JSON_WRITER<OUTPUT_STREAM, SOURCE_ENCODING,
197198
return TRapidJsonWriterBase::Double(d);
198199
}
199200

201+
//! Writes an epoch second timestamp as an epoch millis timestamp
202+
bool Time(core_t::TTime t)
203+
{
204+
return this->Int64(CTimeUtils::toEpochMs(t));
205+
}
200206

201207
//! Push a constant string into a supplied rapidjson object value
202208
//! \p[in] value constant string
@@ -405,8 +411,7 @@ class CRapidJsonWriterBase : public JSON_WRITER<OUTPUT_STREAM, SOURCE_ENCODING,
405411
core_t::TTime value,
406412
TValue &obj) const
407413
{
408-
int64_t javaTimestamp = int64_t(value) * 1000;
409-
TValue v(javaTimestamp);
414+
TValue v(CTimeUtils::toEpochMs(value));
410415
this->addMember(fieldName, v, obj);
411416
}
412417

@@ -552,7 +557,7 @@ class CRapidJsonWriterBase : public JSON_WRITER<OUTPUT_STREAM, SOURCE_ENCODING,
552557

553558
for (const auto &value: values)
554559
{
555-
this->pushBack(value * int64_t(1000), array);
560+
this->pushBack(CTimeUtils::toEpochMs(value), array);
556561
}
557562

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

include/core/CTimeUtils.h

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

67+
//! Converts an epoch seconds timestamp to epoch millis
68+
static int64_t toEpochMs(core_t::TTime t);
6769
//! strptime interface
6870
//! NOTE: the time returned here is a UTC value
6971
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
@@ -500,7 +500,7 @@ void CJsonOutputWriter::writeBucket(bool isInterim,
500500
m_Writer.addIntFieldToObj(DETECTOR_INDEX, detectorIndex, *docPtr);
501501
m_Writer.addIntFieldToObj(BUCKET_SPAN, bucketData.s_BucketSpan, *docPtr);
502502
m_Writer.addStringFieldCopyToObj(JOB_ID, m_JobId, *docPtr);
503-
m_Writer.addIntFieldToObj(TIMESTAMP, bucketTime * 1000, *docPtr);
503+
m_Writer.addTimeFieldToObj(TIMESTAMP, bucketTime, *docPtr);
504504

505505
if (isInterim)
506506
{
@@ -531,7 +531,7 @@ void CJsonOutputWriter::writeBucket(bool isInterim,
531531
}
532532

533533
m_Writer.addStringFieldCopyToObj(JOB_ID, m_JobId, *docPtr);
534-
m_Writer.addIntFieldToObj(TIMESTAMP, bucketTime * 1000, *docPtr);
534+
m_Writer.addTimeFieldToObj(TIMESTAMP, bucketTime, *docPtr);
535535
if (isInterim)
536536
{
537537
m_Writer.addBoolFieldToObj(IS_INTERIM, isInterim, *docPtr);
@@ -551,7 +551,7 @@ void CJsonOutputWriter::writeBucket(bool isInterim,
551551
m_Writer.String(JOB_ID);
552552
m_Writer.String(m_JobId);
553553
m_Writer.String(TIMESTAMP);
554-
m_Writer.Int64(bucketTime * 1000);
554+
m_Writer.Time(bucketTime);
555555

556556
m_Writer.String(ANOMALY_SCORE);
557557
m_Writer.Double(bucketData.s_MaxBucketInfluencerNormalizedAnomalyScore);
@@ -586,7 +586,7 @@ void CJsonOutputWriter::writeBucket(bool isInterim,
586586

587587

588588
m_Writer.addStringFieldCopyToObj(JOB_ID, m_JobId, *docPtr);
589-
m_Writer.addIntFieldToObj(TIMESTAMP, bucketTime * 1000, *docPtr);
589+
m_Writer.addTimeFieldToObj(TIMESTAMP, bucketTime, *docPtr);
590590
m_Writer.addIntFieldToObj(BUCKET_SPAN, bucketData.s_BucketSpan, *docPtr);
591591
if (isInterim)
592592
{
@@ -984,7 +984,7 @@ void CJsonOutputWriter::acknowledgeFlush(const std::string &flushId, core_t::TTi
984984
m_Writer.String(ID);
985985
m_Writer.String(flushId);
986986
m_Writer.String(LAST_FINALIZED_BUCKET_END);
987-
m_Writer.Int64(lastFinalizedBucketEnd * 1000);
987+
m_Writer.Time(lastFinalizedBucketEnd);
988988

989989
m_Writer.EndObject();
990990
m_Writer.EndObject();

lib/api/CModelPlotDataJsonWriter.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ void CModelPlotDataJsonWriter::writeFlatRow(core_t::TTime time,
117117
m_Writer.addIntFieldToObj(DETECTOR_INDEX, detectorIndex, doc);
118118
m_Writer.addStringFieldCopyToObj(FEATURE, feature, doc, true);
119119
// time is in Java format - milliseconds since the epoch
120-
m_Writer.addIntFieldToObj(TIME, time * 1000, doc);
120+
m_Writer.addTimeFieldToObj(TIME, time, doc);
121121
m_Writer.addIntFieldToObj(BUCKET_SPAN, bucketSpan, doc);
122122
if (!partitionFieldName.empty())
123123
{

lib/api/CModelSizeStatsJsonWriter.cc

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

7777
writer.String(TIMESTAMP);
78-
writer.Int64(results.s_BucketStartTime * 1000);
78+
writer.Time(results.s_BucketStartTime);
7979

8080
writer.String(LOG_TIME);
81-
writer.Int64(core::CTimeUtils::now() * 1000);
81+
writer.Time(core::CTimeUtils::now());
8282

8383
writer.EndObject();
8484
}

lib/api/CModelSnapshotJsonWriter.cc

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

63-
// Write as a Java timestamp - ms since the epoch rather than seconds
64-
int64_t javaTimestamp = int64_t(report.s_SnapshotTimestamp) * 1000;
65-
6663
m_Writer.String(TIMESTAMP);
67-
m_Writer.Int64(javaTimestamp);
64+
m_Writer.Time(report.s_SnapshotTimestamp);
6865

6966
m_Writer.String(DESCRIPTION);
7067
m_Writer.String(report.s_Description);
@@ -73,17 +70,13 @@ void CModelSnapshotJsonWriter::write(const SModelSnapshotReport &report)
7370

7471
if (report.s_LatestRecordTime > 0)
7572
{
76-
javaTimestamp = int64_t(report.s_LatestRecordTime) * 1000;
77-
7873
m_Writer.String(LATEST_RECORD_TIME);
79-
m_Writer.Int64(javaTimestamp);
74+
m_Writer.Time(report.s_LatestRecordTime);
8075
}
8176
if (report.s_LatestFinalResultTime > 0)
8277
{
83-
javaTimestamp = int64_t(report.s_LatestFinalResultTime) * 1000;
84-
8578
m_Writer.String(LATEST_RESULT_TIME);
86-
m_Writer.Int64(javaTimestamp);
79+
m_Writer.Time(report.s_LatestFinalResultTime);
8780
}
8881

8982
// write normalizerState here
@@ -111,7 +104,7 @@ void CModelSnapshotJsonWriter::writeQuantileState(const std::string &jobId,
111104
writer.String(QUANTILE_STATE);
112105
writer.String(state);
113106
writer.String(TIMESTAMP);
114-
writer.Int64(time * 1000);
107+
writer.Time(time);
115108
writer.EndObject();
116109
}
117110

lib/core/CTimeUtils.cc

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

64+
int64_t CTimeUtils::toEpochMs(core_t::TTime t)
65+
{
66+
return static_cast<int64_t>(t) * 1000;
67+
}
68+
6469
bool CTimeUtils::strptime(const std::string &format,
6570
const std::string &dateTime,
6671
core_t::TTime &preTime)

lib/core/unittest/CRapidJsonWriterBaseTest.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const std::string NAN_NAME("nan");
5050
const std::string INFINITY_NAME("infinity");
5151
const std::string BOOL_NAME("bool");
5252
const std::string INT_NAME("int");
53+
const std::string TIME_NAME("time");
5354
const std::string UINT_NAME("uint");
5455
const std::string STR_ARRAY_NAME("str[]");
5556
const std::string DOUBLE_ARRAY_NAME("double[]");
@@ -75,6 +76,7 @@ void CRapidJsonWriterBaseTest::testAddFields(void)
7576
writer.addDoubleFieldToObj(INFINITY_NAME, std::numeric_limits<double>::infinity(), doc);
7677
writer.addBoolFieldToObj(BOOL_NAME, false, doc);
7778
writer.addIntFieldToObj(INT_NAME, -9, doc);
79+
writer.addTimeFieldToObj(TIME_NAME, ml::core_t::TTime(1521035866), doc);
7880
writer.addUIntFieldToObj(UINT_NAME, 999999999999999ull, doc);
7981
writer.addStringArrayFieldToObj(STR_ARRAY_NAME, TGenericLineWriter::TStrVec(3, "blah"), doc);
8082
writer.addDoubleArrayFieldToObj(DOUBLE_ARRAY_NAME, TGenericLineWriter::TDoubleVec(10, 1.5), doc);
@@ -97,6 +99,7 @@ void CRapidJsonWriterBaseTest::testAddFields(void)
9799
"\"infinity\":0,"
98100
"\"bool\":false,"
99101
"\"int\":-9,"
102+
"\"time\":1521035866000,"
100103
"\"uint\":999999999999999,"
101104
"\"str[]\":[\"blah\",\"blah\",\"blah\"],"
102105
"\"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
@@ -36,6 +36,9 @@ CppUnit::Test *CTimeUtilsTest::suite()
3636
suiteOfTests->addTest( new CppUnit::TestCaller<CTimeUtilsTest>(
3737
"CTimeUtilsTest::testToLocal",
3838
&CTimeUtilsTest::testToLocal) );
39+
suiteOfTests->addTest( new CppUnit::TestCaller<CTimeUtilsTest>(
40+
"CTimeUtilsTest::testToEpochMs",
41+
&CTimeUtilsTest::testToEpochMs) );
3942
suiteOfTests->addTest( new CppUnit::TestCaller<CTimeUtilsTest>(
4043
"CTimeUtilsTest::testStrptime",
4144
&CTimeUtilsTest::testStrptime) );
@@ -122,6 +125,14 @@ void CTimeUtilsTest::testToLocal(void)
122125
}
123126
}
124127

128+
void CTimeUtilsTest::testToEpochMs(void)
129+
{
130+
CPPUNIT_ASSERT_EQUAL(int64_t(1000), ml::core::CTimeUtils::toEpochMs(ml::core_t::TTime(1)));
131+
CPPUNIT_ASSERT_EQUAL(int64_t(-1000), ml::core::CTimeUtils::toEpochMs(ml::core_t::TTime(-1)));
132+
CPPUNIT_ASSERT_EQUAL(int64_t(1521035866000), ml::core::CTimeUtils::toEpochMs(ml::core_t::TTime(1521035866)));
133+
CPPUNIT_ASSERT_EQUAL(int64_t(-1521035866000), ml::core::CTimeUtils::toEpochMs(ml::core_t::TTime(-1521035866)));
134+
}
135+
125136
void CTimeUtilsTest::testStrptime(void)
126137
{
127138
// 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
@@ -24,6 +24,7 @@ class CTimeUtilsTest : public CppUnit::TestFixture
2424
void testNow(void);
2525
void testToIso8601(void);
2626
void testToLocal(void);
27+
void testToEpochMs(void);
2728
void testStrptime(void);
2829
void testTimezone(void);
2930
void testDateWords(void);

0 commit comments

Comments
 (0)