From b7bb942cadfe3d657895af1557b78acc2559947e Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sun, 5 Aug 2018 15:58:14 -0400 Subject: Tweets store their created time C/C++ time handling is awful, pass it on --- CMakeLists.txt | 3 ++- src/tweet.cpp | 43 +++++++++++++++++++++++++------------------ src/tweet.h | 55 ++++++++++++++++++++++++++++++++----------------------- src/util.cpp | 37 +++++++++++++++++++++++++++++++++++++ src/util.h | 3 +++ 5 files changed, 99 insertions(+), 42 deletions(-) create mode 100644 src/util.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 08851cf..7685af5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,7 +21,8 @@ add_library(twitter++ src/direct_message.cpp src/list.cpp src/user.cpp - src/configuration.cpp) + src/configuration.cpp + src/util.cpp) set_property(TARGET twitter++ PROPERTY CXX_STANDARD 14) set_property(TARGET twitter++ PROPERTY CXX_STANDARD_REQUIRED ON) diff --git a/src/tweet.cpp b/src/tweet.cpp index 1c869f9..1003647 100644 --- a/src/tweet.cpp +++ b/src/tweet.cpp @@ -1,11 +1,12 @@ #include "tweet.h" #include +#include #include "util.h" #include "codes.h" #include "client.h" namespace twitter { - + tweet::tweet(std::string data) try : _valid(true) { @@ -13,14 +14,20 @@ namespace twitter { _id = json["id"].get(); _text = json["text"].get(); _author = std::make_unique(json["user"].dump()); - + + std::tm ctt = { 0 }; + std::stringstream createdAtStream; + createdAtStream << json["created_at"].get(); + createdAtStream >> std::get_time(&ctt, "%a %b %d %H:%M:%S +0000 %Y"); + _created_at = twitter::timegm(&ctt); + if (!json["retweeted_status"].is_null()) { _is_retweet = true; - + _retweeted_status = std::make_unique(json["retweeted_status"].dump()); } - + if (!json["entities"].is_null()) { auto entities = json["entities"]; @@ -39,7 +46,7 @@ namespace twitter { { std::throw_with_nested(malformed_object("tweet", data)); } - + tweet::tweet(const tweet& other) { _valid = other._valid; @@ -47,27 +54,27 @@ namespace twitter { _text = other._text; _author = std::make_unique(*other._author); _is_retweet = other._is_retweet; - + if (_is_retweet) { _retweeted_status = std::make_unique(*other._retweeted_status); } - + _mentions = other._mentions; } - + tweet::tweet(tweet&& other) : tweet() { swap(*this, other); } - + tweet& tweet::operator=(tweet other) { swap(*this, other); - + return *this; } - + void swap(tweet& first, tweet& second) { std::swap(first._valid, second._valid); @@ -78,12 +85,12 @@ namespace twitter { std::swap(first._retweeted_status, second._retweeted_status); std::swap(first._mentions, second._mentions); } - + std::string tweet::generateReplyPrefill(const user& me) const { std::ostringstream output; output << "@" << _author->getScreenName() << " "; - + for (auto mention : _mentions) { if ((mention.first != _author->getID()) && (mention.first != me.getID())) @@ -91,21 +98,21 @@ namespace twitter { output << "@" << mention.second << " "; } } - + return output.str(); } - + std::string tweet::getURL() const { assert(_valid); - + std::ostringstream urlstr; urlstr << "https://twitter.com/"; urlstr << _author->getScreenName(); urlstr << "/statuses/"; urlstr << _id; - + return urlstr.str(); } - + }; diff --git a/src/tweet.h b/src/tweet.h index ae1c916..71a27bd 100644 --- a/src/tweet.h +++ b/src/tweet.h @@ -7,84 +7,93 @@ #include #include #include +#include #include "user.h" namespace twitter { - + class client; - + typedef unsigned long long tweet_id; - + class tweet { public: - + tweet() {} tweet(std::string data); - + tweet(const tweet& other); tweet(tweet&& other); - + tweet& operator=(tweet other); - + friend void swap(tweet& first, tweet& second); - + tweet_id getID() const { assert(_valid); - + return _id; } - + std::string getText() const { assert(_valid); - + return _text; } - + const user& getAuthor() const { assert(_valid); - + return *_author; } + const std::time_t& getCreatedAt() const + { + assert(_valid); + + return _created_at; + } + bool isRetweet() const { assert(_valid); - + return _is_retweet; } - + const tweet& getRetweet() const { assert(_valid && _is_retweet); - + return *_retweeted_status; } - + const std::vector>& getMentions() const { assert(_valid); - + return _mentions; } - + std::string generateReplyPrefill(const user& me) const; - + std::string getURL() const; - + private: - + bool _valid = false; tweet_id _id; std::string _text; std::unique_ptr _author; + std::time_t _created_at; bool _is_retweet = false; std::unique_ptr _retweeted_status; std::vector> _mentions; }; - + }; #endif /* end of include guard: TWEET_H_CE980721 */ diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..5952138 --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,37 @@ +#include "util.h" + +namespace twitter { + + // Eric S Raymond wrote this + /* struct tm to seconds since Unix epoch */ + time_t timegm(struct tm * t) + { + long year; + time_t result; + #define MONTHSPERYEAR 12 /* months per calendar year */ + static const int cumdays[MONTHSPERYEAR] = + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + + /*@ +matchanyintegral @*/ + year = 1900 + t->tm_year + t->tm_mon / MONTHSPERYEAR; + result = (year - 1970) * 365 + cumdays[t->tm_mon % MONTHSPERYEAR]; + result += (year - 1968) / 4; + result -= (year - 1900) / 100; + result += (year - 1600) / 400; + if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0) && + (t->tm_mon % MONTHSPERYEAR) < 2) + result--; + result += t->tm_mday - 1; + result *= 24; + result += t->tm_hour; + result *= 60; + result += t->tm_min; + result *= 60; + result += t->tm_sec; + if (t->tm_isdst == 1) + result -= 3600; + /*@ -matchanyintegral @*/ + return (result); + } + +} diff --git a/src/util.h b/src/util.h index 8cbe054..b950728 100644 --- a/src/util.h +++ b/src/util.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace twitter { @@ -25,6 +26,8 @@ namespace twitter { return result.str(); } + time_t timegm(struct tm * t); + }; #endif /* end of include guard: UTIL_H_440DEAA0 */ -- cgit 1.4.1