xref: /openbmc/phosphor-logging/extensions/openpower-pels/bcd_time.cpp (revision 40fb54935ce7367636a7156039396ee91cc4d5e2)
1 // SPDX-License-Identifier: Apache-2.0
2 // SPDX-FileCopyrightText: Copyright 2019 IBM Corporation
3 
4 #include "bcd_time.hpp"
5 
6 #include <time.h>
7 
8 #include <phosphor-logging/log.hpp>
9 
10 namespace openpower
11 {
12 namespace pels
13 {
14 
operator ==(const BCDTime & right) const15 bool BCDTime::operator==(const BCDTime& right) const
16 {
17     return (yearMSB == right.yearMSB) && (yearLSB == right.yearLSB) &&
18            (month == right.month) && (day == right.day) &&
19            (hour == right.hour) && (minutes == right.minutes) &&
20            (seconds == right.seconds) && (hundredths == right.hundredths);
21 }
22 
operator !=(const BCDTime & right) const23 bool BCDTime::operator!=(const BCDTime& right) const
24 {
25     return !(*this == right);
26 }
27 
getBCDTime(std::chrono::time_point<std::chrono::system_clock> & time)28 BCDTime getBCDTime(std::chrono::time_point<std::chrono::system_clock>& time)
29 {
30     BCDTime bcd;
31 
32     using namespace std::chrono;
33     time_t t = system_clock::to_time_t(time);
34     tm* gmTime = gmtime(&t);
35     assert(gmTime != nullptr);
36 
37     int year = 1900 + gmTime->tm_year;
38     bcd.yearMSB = toBCD(year / 100);
39     bcd.yearLSB = toBCD(year % 100);
40     bcd.month = toBCD(gmTime->tm_mon + 1);
41     bcd.day = toBCD(gmTime->tm_mday);
42     bcd.hour = toBCD(gmTime->tm_hour);
43     bcd.minutes = toBCD(gmTime->tm_min);
44     bcd.seconds = toBCD(gmTime->tm_sec);
45 
46     auto ms = duration_cast<milliseconds>(time.time_since_epoch()).count();
47     int hundredths = (ms % 1000) / 10;
48     bcd.hundredths = toBCD(hundredths);
49 
50     return bcd;
51 }
52 
getBCDTime(uint64_t epochMS)53 BCDTime getBCDTime(uint64_t epochMS)
54 {
55     std::chrono::milliseconds ms{epochMS};
56     std::chrono::time_point<std::chrono::system_clock> time{ms};
57 
58     return getBCDTime(time);
59 }
60 
getMillisecondsSinceEpoch(const BCDTime & bcdTime)61 uint64_t getMillisecondsSinceEpoch(const BCDTime& bcdTime)
62 {
63     // Convert a UTC tm struct to a UTC time_t struct to a timepoint.
64     int year = (fromBCD(bcdTime.yearMSB) * 100) + fromBCD(bcdTime.yearLSB);
65     tm utcTime;
66     utcTime.tm_year = year - 1900;
67     utcTime.tm_mon = fromBCD(bcdTime.month) - 1;
68     utcTime.tm_mday = fromBCD(bcdTime.day);
69     utcTime.tm_hour = fromBCD(bcdTime.hour);
70     utcTime.tm_min = fromBCD(bcdTime.minutes);
71     utcTime.tm_sec = fromBCD(bcdTime.seconds);
72     utcTime.tm_isdst = 0;
73 
74     time_t t = timegm(&utcTime);
75     auto timepoint = std::chrono::system_clock::from_time_t(t);
76     int milliseconds = fromBCD(bcdTime.hundredths) * 10;
77     timepoint += std::chrono::milliseconds(milliseconds);
78 
79     return std::chrono::duration_cast<std::chrono::milliseconds>(
80                timepoint.time_since_epoch())
81         .count();
82 }
83 
operator >>(Stream & s,BCDTime & time)84 Stream& operator>>(Stream& s, BCDTime& time)
85 {
86     s >> time.yearMSB >> time.yearLSB >> time.month >> time.day >> time.hour;
87     s >> time.minutes >> time.seconds >> time.hundredths;
88     return s;
89 }
90 
operator <<(Stream & s,const BCDTime & time)91 Stream& operator<<(Stream& s, const BCDTime& time)
92 {
93     s << time.yearMSB << time.yearLSB << time.month << time.day << time.hour;
94     s << time.minutes << time.seconds << time.hundredths;
95     return s;
96 }
97 
98 } // namespace pels
99 } // namespace openpower
100