xref: /openbmc/phosphor-logging/extensions/openpower-pels/bcd_time.cpp (revision 253bfb72ef73b035eda2b2e719d4e4922af7ae58)
1711d51d8SMatt Spinler /**
2711d51d8SMatt Spinler  * Copyright © 2019 IBM Corporation
3711d51d8SMatt Spinler  *
4711d51d8SMatt Spinler  * Licensed under the Apache License, Version 2.0 (the "License");
5711d51d8SMatt Spinler  * you may not use this file except in compliance with the License.
6711d51d8SMatt Spinler  * You may obtain a copy of the License at
7711d51d8SMatt Spinler  *
8711d51d8SMatt Spinler  *     http://www.apache.org/licenses/LICENSE-2.0
9711d51d8SMatt Spinler  *
10711d51d8SMatt Spinler  * Unless required by applicable law or agreed to in writing, software
11711d51d8SMatt Spinler  * distributed under the License is distributed on an "AS IS" BASIS,
12711d51d8SMatt Spinler  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13711d51d8SMatt Spinler  * See the License for the specific language governing permissions and
14711d51d8SMatt Spinler  * limitations under the License.
15711d51d8SMatt Spinler  */
16df797f2bSMatt Spinler #include "bcd_time.hpp"
17df797f2bSMatt Spinler 
180bf04b5dSMatt Spinler #include <time.h>
190bf04b5dSMatt Spinler 
200bf04b5dSMatt Spinler #include <phosphor-logging/log.hpp>
210bf04b5dSMatt Spinler 
22df797f2bSMatt Spinler namespace openpower
23df797f2bSMatt Spinler {
24df797f2bSMatt Spinler namespace pels
25df797f2bSMatt Spinler {
26df797f2bSMatt Spinler 
operator ==(const BCDTime & right) const27df797f2bSMatt Spinler bool BCDTime::operator==(const BCDTime& right) const
28df797f2bSMatt Spinler {
29df797f2bSMatt Spinler     return (yearMSB == right.yearMSB) && (yearLSB == right.yearLSB) &&
30df797f2bSMatt Spinler            (month == right.month) && (day == right.day) &&
31df797f2bSMatt Spinler            (hour == right.hour) && (minutes == right.minutes) &&
32df797f2bSMatt Spinler            (seconds == right.seconds) && (hundredths == right.hundredths);
33df797f2bSMatt Spinler }
34df797f2bSMatt Spinler 
operator !=(const BCDTime & right) const35df797f2bSMatt Spinler bool BCDTime::operator!=(const BCDTime& right) const
36df797f2bSMatt Spinler {
37df797f2bSMatt Spinler     return !(*this == right);
38df797f2bSMatt Spinler }
39df797f2bSMatt Spinler 
getBCDTime(std::chrono::time_point<std::chrono::system_clock> & time)40df797f2bSMatt Spinler BCDTime getBCDTime(std::chrono::time_point<std::chrono::system_clock>& time)
41df797f2bSMatt Spinler {
42df797f2bSMatt Spinler     BCDTime bcd;
43df797f2bSMatt Spinler 
44df797f2bSMatt Spinler     using namespace std::chrono;
45df797f2bSMatt Spinler     time_t t = system_clock::to_time_t(time);
46*253bfb72SPatrick Williams     tm* gmTime = gmtime(&t);
47*253bfb72SPatrick Williams     assert(gmTime != nullptr);
48df797f2bSMatt Spinler 
49*253bfb72SPatrick Williams     int year = 1900 + gmTime->tm_year;
50df797f2bSMatt Spinler     bcd.yearMSB = toBCD(year / 100);
51df797f2bSMatt Spinler     bcd.yearLSB = toBCD(year % 100);
52*253bfb72SPatrick Williams     bcd.month = toBCD(gmTime->tm_mon + 1);
53*253bfb72SPatrick Williams     bcd.day = toBCD(gmTime->tm_mday);
54*253bfb72SPatrick Williams     bcd.hour = toBCD(gmTime->tm_hour);
55*253bfb72SPatrick Williams     bcd.minutes = toBCD(gmTime->tm_min);
56*253bfb72SPatrick Williams     bcd.seconds = toBCD(gmTime->tm_sec);
57df797f2bSMatt Spinler 
58df797f2bSMatt Spinler     auto ms = duration_cast<milliseconds>(time.time_since_epoch()).count();
59df797f2bSMatt Spinler     int hundredths = (ms % 1000) / 10;
60df797f2bSMatt Spinler     bcd.hundredths = toBCD(hundredths);
61df797f2bSMatt Spinler 
62df797f2bSMatt Spinler     return bcd;
63df797f2bSMatt Spinler }
64df797f2bSMatt Spinler 
getBCDTime(uint64_t epochMS)655fa87f08SMatt Spinler BCDTime getBCDTime(uint64_t epochMS)
665fa87f08SMatt Spinler {
675fa87f08SMatt Spinler     std::chrono::milliseconds ms{epochMS};
685fa87f08SMatt Spinler     std::chrono::time_point<std::chrono::system_clock> time{ms};
695fa87f08SMatt Spinler 
705fa87f08SMatt Spinler     return getBCDTime(time);
715fa87f08SMatt Spinler }
725fa87f08SMatt Spinler 
getMillisecondsSinceEpoch(const BCDTime & bcdTime)730bf04b5dSMatt Spinler uint64_t getMillisecondsSinceEpoch(const BCDTime& bcdTime)
740bf04b5dSMatt Spinler {
750bf04b5dSMatt Spinler     // Convert a UTC tm struct to a UTC time_t struct to a timepoint.
760bf04b5dSMatt Spinler     int year = (fromBCD(bcdTime.yearMSB) * 100) + fromBCD(bcdTime.yearLSB);
770bf04b5dSMatt Spinler     tm utcTime;
780bf04b5dSMatt Spinler     utcTime.tm_year = year - 1900;
790bf04b5dSMatt Spinler     utcTime.tm_mon = fromBCD(bcdTime.month) - 1;
800bf04b5dSMatt Spinler     utcTime.tm_mday = fromBCD(bcdTime.day);
810bf04b5dSMatt Spinler     utcTime.tm_hour = fromBCD(bcdTime.hour);
820bf04b5dSMatt Spinler     utcTime.tm_min = fromBCD(bcdTime.minutes);
830bf04b5dSMatt Spinler     utcTime.tm_sec = fromBCD(bcdTime.seconds);
840bf04b5dSMatt Spinler     utcTime.tm_isdst = 0;
850bf04b5dSMatt Spinler 
860bf04b5dSMatt Spinler     time_t t = timegm(&utcTime);
870bf04b5dSMatt Spinler     auto timepoint = std::chrono::system_clock::from_time_t(t);
880bf04b5dSMatt Spinler     int milliseconds = fromBCD(bcdTime.hundredths) * 10;
890bf04b5dSMatt Spinler     timepoint += std::chrono::milliseconds(milliseconds);
900bf04b5dSMatt Spinler 
910bf04b5dSMatt Spinler     return std::chrono::duration_cast<std::chrono::milliseconds>(
920bf04b5dSMatt Spinler                timepoint.time_since_epoch())
930bf04b5dSMatt Spinler         .count();
940bf04b5dSMatt Spinler }
950bf04b5dSMatt Spinler 
operator >>(Stream & s,BCDTime & time)96df797f2bSMatt Spinler Stream& operator>>(Stream& s, BCDTime& time)
97df797f2bSMatt Spinler {
98df797f2bSMatt Spinler     s >> time.yearMSB >> time.yearLSB >> time.month >> time.day >> time.hour;
99df797f2bSMatt Spinler     s >> time.minutes >> time.seconds >> time.hundredths;
100df797f2bSMatt Spinler     return s;
101df797f2bSMatt Spinler }
102df797f2bSMatt Spinler 
operator <<(Stream & s,const BCDTime & time)103d7b004bfSMatt Spinler Stream& operator<<(Stream& s, const BCDTime& time)
104df797f2bSMatt Spinler {
105df797f2bSMatt Spinler     s << time.yearMSB << time.yearLSB << time.month << time.day << time.hour;
106df797f2bSMatt Spinler     s << time.minutes << time.seconds << time.hundredths;
107df797f2bSMatt Spinler     return s;
108df797f2bSMatt Spinler }
109df797f2bSMatt Spinler 
110df797f2bSMatt Spinler } // namespace pels
111df797f2bSMatt Spinler } // namespace openpower
112