0

I know that this question may have been asked before, but this is a follow up of one of my previous questions found here. What makes this unique from the other questions is that I'm looking for something that is current and relevant to my compiler: Visual Studio 2017 using C++17 - latest draft standard.

I know that in time C++20 will be released and available for Visual Studio 2019 in which I'm looking forward to. However at the time being; I'm still using Visual Studio 2017 on Windows 7, and I'm currently bounded to C++17. I have found this Q/A that is similar to this that had offered great answers, however when I started to use <ctime> or <time.h> functions such as:

std::gmtime()
std::localtime()

My compiler is yelling at me that these functions are marked as unsafe and deprecated. I was attempting to write a function like this:

-DateAndTime.h-

#pragma once

#include <ctime>
#include <iomanip>
#include <iostream>
#include <sstream>  

namespace util {

    enum class TimeLocale {
        LOCAL = 0x01,
        GMT   = 0x02,
        BOTH = (LOCAL | GMT)
    };

    inline TimeLocale operator|(TimeLocale a, TimeLocale b) {
        return static_cast<TimeLocale>(static_cast<int>(a) | static_cast<int>(b)); 
    }

#pragma warning( push )
#pragma warning( disable : 4996 )
    inline void currentDateAndTime(std::stringstream& stream, TimeLocale locale) {
        std::time_t t = std::time(nullptr);

        if (locale == TimeLocale::GMT) {
            stream << "UTC:   " << std::put_time( std::gmtime(&t), "%c, %Z") << '\n';
        }

        if (locale == TimeLocale::LOCAL) {
            stream << "LOCAL: " << std::put_time(std::localtime(&t), "%c, %Z") << '\n';
        }

        if (locale == TimeLocale::BOTH) {
            stream << "UTC:   " << std::put_time(std::gmtime(&t), "%c, %Z") << '\n'
                   << "LOCAL: " << std::put_time(std::localtime(&t), "%c, %Z") << '\n';
        }
    }
#pragma warning( pop )

} // namespace util

-main.cpp-

#include "DateAndTime.h"

#include <iostream>
#include <sstream>

using namespace util;

int main() {
    try {
        std::stringstream stream1;
        getCurrentTime(stream1, TimeLocale::GMT);
        std::cout << stream1.str() << '\n';

        std::stringstream stream2;
        getCurrentTime(stream2, TimeLocale::LOCAL);
        std::cout << stream2.str() << '\n';

        std::stringstream stream3;
        getCurrentTime(stream3, TimeLocale::BOTH);
        std::cout << stream3.str() << '\n';

        std::stringstream stream4;
        getCurrentTime(stream4, TimeLocale::GMT | TimeLocale::LOCAL);
        std::cout << stream4.str() << '\n';         

    // ExceptionHandler is one of my class's and can be ignored in this context
    // You can replace this with std::exception, std::cerr, etc...
    } catch ( ExceptionHandler& e ) {
        std::cout << "Exception Thrown: " << e.getMessage() << std::endl;
        return EXIT_FAILURE;
    } catch (...) {
        std::cout << __FUNCTION__ << " Caught Unknown Exception" << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

This works fine if I use #pragma warning( disable : 4996 )

And I am getting a nice output like this:

UTC:   02/20/19 05:44:38, Eastern Standard Time

Local: 02/20/19 00:44:38, Eastern Standard Time

UTC:   02/20/19 05:44:38, Eastern Standard Time
Local: 02/20/19 00:44:38, Eastern Standard Time

UTC:   02/20/19 05:44:38, Eastern Standard Time
Local: 02/20/19 00:44:38, Eastern Standard Time

Which looks great. However, I'd prefer to not use any functions that are marked deprecated, that are not platform specific, that are generic, portable and cross platform as possible that is currently available in C++17. Preferably something from the standard library. I don't want to use a third party library nor boost. std::chrono would be a nice option however their calendar section won't be available until the full release of C++20. What kind of options am I left with?

Francis Cugler
  • 7,788
  • 2
  • 28
  • 59

1 Answers1

1

The functions gmtime and localtime aren't deprecated.

Only for Visual Studio they are deprecated because Visual Studio offer the alternative gmtime_s and localtime_s, so I would use those functions. And under Unix you have gmtime_r and localtime_r if you want to be thread-safe. See also this answer

Write an inline gmtime_r and localtime_r under Windows that calls gmtime_s and localtime_s and you have an almost standard cross plattform solution until C++20.

andreaplanet
  • 731
  • 5
  • 14