2

There are many links to achieve this but I can't actually find a code example from the accepted answers (that doesn't use boost), what would be the most efficient way to have something such as this:

char date[] = "2021-01-01";
long double seconds = SecondsSince1970(date);

and an output of something like 10000000000 or however many seconds that is?

Edit: (achieved in C++ by)

std::tm t = {};
std::istringstream ss("2010-11-04T23:23:01Z");
if (ss >> std::get_time(&t, "%Y-%m-%dT%H:%M:%S")){
    std::cout << std::put_time(&t, "%c") << "\n"  << std::mktime(&t) << "\n";
} 

I guess an extension to this question is how can I replicate this C++ code but without the use of istringstream so it doesn't have to allocate memory, rather it just goes directly from the raw char [] array to seconds?

1 Answers1

2

You can do it in 3 simple steps:

  • sscanf the string (Bonus - Check valid date)
  • Get the days since 1970
  • Multiply by 24 * 60 * 60

#include <stdio.h>

int leap_years(int month, int year)
{
    int years = year;

    if (month <= 2)
    {
        years--;
    }
    return (years / 4) - (years / 100) + (years / 400);
}

int days_diff(int day1, int month1, int year1,
              int day2, int month2, int year2)
{
    static const int days[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
    long int days1 = (year1 * 365) + day1;
    long int days2 = (year2 * 365) + day2;

    days1 += days[month1 - 1] + leap_years(month1, year1);
    days2 += days[month2 - 1] + leap_years(month2, year2);
    return (int)(days2 - days1);
}

int year_isleap(int year)
{
    return (((year % 4) == 0) && ((year % 100) != 0)) || ((year % 400) == 0);
}

int month_days(int month, int year)
{
    static const int days[2][12] =
    {
        {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
        {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    };
    int leap = year_isleap(year);

    return days[leap][month - 1];
}

int date_isvalid(int day, int month, int year)
{
    if ((year < 0) || (year > 9999))
    {
        return 0;
    }
    if ((month < 1) || (month > 12))
    {
        return 0;
    }
    if ((day < 1) || (day > month_days(month, year)))
    {
        return 0;
    }
    return 1;
}

int main(void)
{
    int d, m, y;

    if ((sscanf("2021-01-01", "%d-%d-%d", &y, &m, &d) == 3) &&
        (date_isvalid(d, m, y)))
    {
        long double seconds = days_diff(1, 1, 1970, d, m, y) * 24 * 60 *60;

        printf("%.0Lf\n", seconds);
    }
    else
    {
        puts("Wrong date");
    }
    return(0);
}

Output:

1609459200
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
  • Sorry, I'll edit the question. I think your answer is very useful but I should have specified a bit clearer. Please leave it though, I'm sure ill need it in the future –  Mar 27 '21 at 07:20
  • @AndySukowski-Bang it would be a bit difficult to get the number of seconds since epoch from `"2021-01-01"` with `time(NULL)`? – David C. Rankin Mar 27 '21 at 07:28
  • Wrong David `:)` (too many of them around tonight) – David C. Rankin Mar 27 '21 at 07:32
  • What about, with my edit, the C++ way but without `istringstream`? Is that possible, I want to directly achieve it from my `char []` so theres no allocations after that, just straight from `char []` to seconds? –  Mar 27 '21 at 07:37
  • Can you update it so it accounts for leap years such as python `time.time()` to return the same result? Sorry i know this might be a bit complicated I just need that time as specific as that since im going over data from history where it may or may not be in 29th feb and what not. I know you put leap year, but that doesn't return the same time as `time.time()` in python/ –  Mar 27 '21 at 07:50
  • @prtwrt I don't get you, leap years are also calculated and I'm not familiar with Python, what is the exact expected result? – David Ranieri Mar 27 '21 at 07:54
  • um, im not quite sure how to implement exact time into your answer, but say i input the exact time it is now, I need it to return exactly `1616831759.302955` for 6:56PM (around 10-20s), 27 march 2021 AEST –  Mar 27 '21 at 07:56
  • @prtwrt Why is it a floating point number? – Andy Sukowski-Bang Mar 27 '21 at 07:59
  • i guess milliseconds, yeah sorry disregard that decimal –  Mar 27 '21 at 07:59