Formats a date to a relative date (ie 1 month ago) Expects the format "YYYY-MM-DD at HH:MM (UTC)" */
| 161 | Expects the format "YYYY-MM-DD at HH:MM (UTC)" |
| 162 | */ |
| 163 | std::string StringUtils::RelativeDate(std::string dateString) { |
| 164 | // Parse the date to a unix timestamp |
| 165 | struct tm tmStruct{}; |
| 166 | int argsParsed = sscanf(dateString.c_str(), "%d-%d-%d at %d:%d", |
| 167 | &tmStruct.tm_year, |
| 168 | &tmStruct.tm_mon, |
| 169 | &tmStruct.tm_mday, |
| 170 | &tmStruct.tm_hour, |
| 171 | &tmStruct.tm_min); |
| 172 | |
| 173 | // If we failed to parse everything, then just return |
| 174 | // the unformatted tring. |
| 175 | if(argsParsed < 5) { |
| 176 | return dateString; |
| 177 | } |
| 178 | |
| 179 | // Fix values |
| 180 | tmStruct.tm_year -= 1900; |
| 181 | tmStruct.tm_mon--; |
| 182 | |
| 183 | time_t then = mktime(&tmStruct); |
| 184 | time_t now = time(nullptr); |
| 185 | time_t ago = now - then; |
| 186 | |
| 187 | int agoSimplified = 0; |
| 188 | std::string agoString; |
| 189 | |
| 190 | if (ago < SEC_PER_DAY) { |
| 191 | return Lang::get("TODAY"); |
| 192 | } else if (ago < SEC_PER_MONTH) { |
| 193 | agoSimplified = ago / SEC_PER_DAY; |
| 194 | agoString = agoSimplified == 1 ? "DAY_AGO" : "DAYS_AGO"; |
| 195 | } else if (ago < SEC_PER_YEAR) { |
| 196 | agoSimplified = ago / SEC_PER_MONTH; |
| 197 | agoString = agoSimplified == 1 ? "MONTH_AGO" : "MONTHS_AGO"; |
| 198 | } else { |
| 199 | agoSimplified = ago / SEC_PER_YEAR; |
| 200 | agoString = agoSimplified == 1 ? "YEAR_AGO" : "YEARS_AGO"; |
| 201 | } |
| 202 | |
| 203 | char out[256]; |
| 204 | snprintf(out, sizeof(out), Lang::get(agoString).c_str(), agoSimplified, 1900 + tmStruct.tm_year, 1 + tmStruct.tm_mon, tmStruct.tm_mday); |
| 205 | return out; |
| 206 | } |