diff options
1 files changed, 174 insertions, 0 deletions
| -rw-r--r-- | Year 1/Object-oriented Programming/Project 1/src/Generic/Date/Date.cpp | 174 |
diff --git a/Year 1/Object-oriented Programming/Project 1/src/Generic/Date/Date.cpp b/Year 1/Object-oriented Programming/Project 1/src/Generic/Date/Date.cpp new file mode 100644 index 0000000..7c8f4d9 --- /dev/null +++ b/Year 1/Object-oriented Programming/Project 1/src/Generic/Date/Date.cpp @@ -0,0 +1,174 @@ +#include "Date.h" +#include <cstring> + +/* Private */ + +bool Date::isLeapYear() { + // Implements https://en.wikipedia.org/wiki/Leap_year#Gregorian_calendar + return year % 400 == 0 || year % 100 != 0 || year % 4 == 0; +} + +unsigned short Date::daysInMonth() { + if (month == 2) + return 28 + isLeapYear(); + if (month <= 7) + return 30 + month % 2; + return 31 - month % 2; +} + +/* Public */ + +Date::Date() : Date(01, 05, 2022) {} + +/*! \param str C-style string + * + * Values are initialized with zeroes. Then it parses the string: + * + * Skips spaces, saves day with atoi, skips two characters, + * skips spaces, saves month with atoi, skips two characters, + * skips spaces, saves year with atoi. + * + * Values are validated with setters. + * You should always have spaces between day, month and year and no non-numeric characters between them. + * + * \remark If there are non-numeric characters, as per atoi() spec, the appropriate property is zero. + */ +Date::Date(const char* str) : Date(0, 0, 0) { + while (*str == ' ' && *str != '\0') str++; + set_day(atoi(str)); + str += 2; + while (*str == ' ' && *str != '\0') str++; + set_month(atoi(str)); + str += 2; + while (*str == ' ' && *str != '\0') str++; + set_year(atoi(str)); +} + +/*! + * Initializes values with zeroes and then uses setters to save the function arguments. + */ +Date::Date(unsigned short day, unsigned short month, unsigned short year) { + this->day = this->month = this->year = 0; + set_day(day); + set_month(month); + set_year(year); +} + +unsigned short Date::get_day() const { + return day; +} + +/*! \return Whether newDay was saved or not + * + * If newDay is equal to 0, or is more than the appropriate days in the month, the day isn't set. + */ +bool Date::set_day(unsigned short newDay) { + if (newDay == 0 || newDay > daysInMonth()) + return false; + day = newDay; + return true; +} + +unsigned short Date::get_month() const { + return month; +} + +/*! \return Whether newMonth was saved or not + * + * If newMonth is equal to 0 or is more than 12, the month isn't set. + */ +bool Date::set_month(unsigned short newMonth) { + if (newMonth == 0 || newMonth > 12) + return false; + month = newMonth; + return true; +} + +unsigned short Date::get_year() const { + return year; +} + +/*! \return Whether year was saved or not + * + * Year isn't set when newYear is zero + */ +bool Date::set_year(unsigned short newYear) { + if (newYear == 0) + return false; + year = newYear; + return true; +} + +int digitToChar(unsigned digit) { + if (digit <= 9) + return '0' + digit; + return ' '; +} + +/*! \return String object in the format "day.month.year" + * + * \note Currently there isn't any way to change the formatting + */ +String Date::createString() const { + String out; + return ((((out += day) += ".") += month) += ".") += year; +} + +/*! \param istr An input stream + * + * Directly reads bytes from stream (calls read() function). + * + * \remark Doesn't alter the stream in any other way. + * \note Best used with binary ifstream + */ +void Date::read(std::istream& istr) { + istr.read((char*)&day, sizeof(day)); + istr.read((char*)&month, sizeof(month)); + istr.read((char*)&year, sizeof(year)); +} + +/*! \param ostr An output stream + * + * Directly writes bytes to stream (calls write() function). + * + * \remark Doesn't alter the stream in any other way. + * \note Best used with binary ofstream + */ +void Date::write(std::ostream& ostr) { + ostr.write((char*)&day, sizeof(day)); + ostr.write((char*)&month, sizeof(month)); + ostr.write((char*)&year, sizeof(year)); +} + +/*! \returns -1 if this < other, 1 if this > other, 0 if this == other + */ +int Date::compare(const Date& other) const { + if (year < other.year || month < other.month || day < other.day) + return -1; + return year > other.year || month > other.month || day > other.day; +} + + +/* Outside of class */ + +/*! + * Uses the stream's >> operator to read and parse the day, month and year. + * + * \note Best used with std::cin or text std::ifstream + */ +std::istream& operator>>(std::istream& istr, Date& dt) { + unsigned short d, M, y; + istr >> d >> M >> y; + dt = Date(d, M, y); + return istr; +} + +/*! + * Uses the stream's << operator to write the date in the format "day.month.year" + * + * \note Best used with std::cout or text std::ofstream + */ +std::ostream& operator<<(std::ostream& ostr, const Date& dt) { + ostr << dt.get_day() << "." << dt.get_month() << "." << dt.get_year(); + return ostr; +} |
