8#include <botan/asn1_obj.h> 
   10#include <botan/assert.h> 
   11#include <botan/ber_dec.h> 
   12#include <botan/der_enc.h> 
   13#include <botan/exceptn.h> 
   14#include <botan/internal/calendar.h> 
   15#include <botan/internal/fmt.h> 
   16#include <botan/internal/parsing.h> 
   29   m_month = cal.
month();
 
 
   44   if(t_spec.size() == 13) {
 
   46   } 
else if(t_spec.size() == 15) {
 
   49      throw Invalid_Argument(
"Time string could not be parsed as GeneralizedTime or UTCTime.");
 
 
   70   uint32_t full_year = m_year;
 
   73      if(m_year < 1950 || m_year >= 2050) {
 
   77      full_year = (m_year >= 2000) ? (m_year - 2000) : (m_year - 1900);
 
   80   const uint64_t year_factor = 10000000000;
 
   81   const uint64_t mon_factor = 100000000;
 
   82   const uint64_t day_factor = 1000000;
 
   83   const uint64_t hour_factor = 10000;
 
   84   const uint64_t min_factor = 100;
 
   86   const uint64_t int_repr = year_factor * full_year + mon_factor * m_month + day_factor * m_day +
 
   87                             hour_factor * m_hour + min_factor * m_minute + m_second;
 
   89   std::string repr = std::to_string(int_repr) + 
"Z";
 
   93   const std::string zero_padding(desired_size - repr.size(), 
'0');
 
   95   return zero_padding + repr;
 
 
  100      throw Invalid_State(
"ASN1_Time::readable_string: No time set");
 
  104   std::stringstream output;
 
  105   output << std::setfill(
'0') << std::setw(4) << m_year << 
"/" << std::setw(2) << m_month << 
"/" << std::setw(2)
 
  106          << m_day << 
" " << std::setw(2) << m_hour << 
":" << std::setw(2) << m_minute << 
":" << std::setw(2)
 
  107          << m_second << 
" UTC";
 
 
  113   return (m_year != 0);
 
 
  118      throw Invalid_State(
"ASN1_Time::cmp: Cannot compare empty times");
 
  121   constexpr int32_t EARLIER = -1;
 
  122   constexpr int32_t LATER = 1;
 
  123   constexpr int32_t SAME_TIME = 0;
 
  125   if(m_year < other.m_year) {
 
  128   if(m_year > other.m_year) {
 
  131   if(m_month < other.m_month) {
 
  134   if(m_month > other.m_month) {
 
  137   if(m_day < other.m_day) {
 
  140   if(m_day > other.m_day) {
 
  143   if(m_hour < other.m_hour) {
 
  146   if(m_hour > other.m_hour) {
 
  149   if(m_minute < other.m_minute) {
 
  152   if(m_minute > other.m_minute) {
 
  155   if(m_second < other.m_second) {
 
  158   if(m_second > other.m_second) {
 
 
  165void ASN1_Time::set_to(std::string_view t_spec, 
ASN1_Type spec_tag) {
 
  167                   "Invalid tag for ASN1_Time");
 
  170      BOTAN_ARG_CHECK(t_spec.size() == 15, 
"Invalid GeneralizedTime input string");
 
  175   BOTAN_ARG_CHECK(t_spec.back() == 
'Z', 
"Botan does not support ASN1 times with timezones other than Z");
 
  177   const size_t field_len = 2;
 
  179   const size_t year_start = 0;
 
  181   const size_t month_start = year_start + year_len;
 
  182   const size_t day_start = month_start + field_len;
 
  183   const size_t hour_start = day_start + field_len;
 
  184   const size_t min_start = hour_start + field_len;
 
  185   const size_t sec_start = min_start + field_len;
 
  187   m_year = 
to_u32bit(t_spec.substr(year_start, year_len));
 
  188   m_month = 
to_u32bit(t_spec.substr(month_start, field_len));
 
  189   m_day = 
to_u32bit(t_spec.substr(day_start, field_len));
 
  190   m_hour = 
to_u32bit(t_spec.substr(hour_start, field_len));
 
  191   m_minute = 
to_u32bit(t_spec.substr(min_start, field_len));
 
  192   m_second = 
to_u32bit(t_spec.substr(sec_start, field_len));
 
  203   if(!passes_sanity_check()) {
 
  204      throw Invalid_Argument(
fmt(
"ASN1_Time string '{}' does not seem to be valid", t_spec));
 
  211bool ASN1_Time::passes_sanity_check()
 const {
 
  213   if(m_year < 1950 || m_year > 3100) {
 
  216   if(m_month == 0 || m_month > 12) {
 
  220   const uint32_t days_in_month[12] = {31, 28 + 1, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
  222   if(m_day == 0 || m_day > days_in_month[m_month - 1]) {
 
  226   if(m_month == 2 && m_day == 29) {
 
  227      if(m_year % 4 != 0) {
 
  231      if(m_year % 100 == 0 && m_year % 400 != 0) {
 
  236   if(m_hour >= 24 || m_minute >= 60 || m_second > 60) {
 
  268   return (t1.
cmp(t2) == 0);
 
 
  272   return (t1.
cmp(t2) != 0);
 
 
  276   return (t1.
cmp(t2) <= 0);
 
 
  280   return (t1.
cmp(t2) >= 0);
 
 
  284   return (t1.
cmp(t2) < 0);
 
 
  288   return (t1.
cmp(t2) > 0);
 
 
#define BOTAN_ARG_CHECK(expr, msg)
 
uint64_t time_since_epoch() const
Return time since epoch.
 
std::chrono::system_clock::time_point to_std_timepoint() const
Returns a STL timepoint object.
 
void decode_from(BER_Decoder &from) override
 
static ASN1_Time from_seconds_since_epoch(uint64_t seconds)
Create an ASN1_Time from seconds since epoch.
 
std::string to_string() const
Return an internal string representation of the time.
 
ASN1_Time()=default
Create an invalid ASN1_Time.
 
bool time_is_set() const
Return if the time has been set somehow.
 
int32_t cmp(const ASN1_Time &other) const
Compare this time against another.
 
void encode_into(DER_Encoder &to) const override
DER encode a ASN1_Time.
 
std::string readable_string() const
Returns a human friendly string replesentation of no particular formatting.
 
BER_Object get_next_object()
 
DER_Encoder & add_object(ASN1_Type type_tag, ASN1_Class class_tag, const uint8_t rep[], size_t length)
 
uint64_t seconds_since_epoch() const
 
std::chrono::system_clock::time_point to_std_timepoint() const
 
std::string to_string(const BER_Object &obj)
 
uint32_t to_u32bit(std::string_view str_view)
 
std::string fmt(std::string_view format, const T &... args)
 
bool operator<(const OID &a, const OID &b)
 
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
 
bool operator>=(const ASN1_Time &x, const ASN1_Time &y)
 
bool operator==(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
 
bool operator>(const ASN1_Time &x, const ASN1_Time &y)
 
bool operator<=(const ASN1_Time &x, const ASN1_Time &y)