Trouble making localtime_s work

I have the following code snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#define __STDC_WANT_LIB_EXT1__ 1
#include <time.h>
.
.
.
std::string TimeStamp()
	 {
         #ifdef __STDC_LIB_EXT1__
		  char str[9];

		  // Get the time, and convert it to struct tm format.
		  time_t a = time(nullptr);
		  struct tm *time_info;

		  struct tm *b = localtime_s(&time_info, &a);

		  // Print the time to the string.
		  strftime(str, 9, "%H:%M:%S", b);

		  return str;
         #endif
	 }


localtime_s won't work without the ifdef/endif but everything that's between them is basically invisible. I don't understand. I'm trying to follow the example provided here:

http://en.cppreference.com/w/c/chrono/localtime

What am I doing wrong?
Last edited on
Your function says, on line 6, that it returns a string. But on line 20, what you're trying to return is not a string.
std::string

This is C++

localtime_s(&time_info, &a);

This is C (and an optional part of C at that)

Which language are you trying to use?

In C++, consider Microsoft's localtime_s https://msdn.microsoft.com/en-us/library/a442x3ye.aspx or POSIX localtime_r http://pubs.opengroup.org/onlinepubs/9699919799/functions/localtime.html (that C function is essentially a standardization of those two) or use a real date/time library, such as boost.date_time http://www.boost.org/doc/libs/1_60_0/doc/html/date_time.html or Howard Hinnant's date.h http://howardhinnant.github.io/date_v2.html
Last edited on
It was an old BasicLib written back in 2003 that I was trying to make work for a game that I'm writing now. Here's the full file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
#include "BasicLibTime.h"
#include "BasicLibString.h"

// ====================================================================================================================
//  Include Files.
// ====================================================================================================================
#include <time.h>
#ifdef WIN32
#include "windows.h"
#else
#include <sys/time.h>
#endif

namespace BasicLib
{
	 // ================================================================================================================
	 // This is a hidden class, designed to initialize the win32 performance counter frequency value.
	 // ================================================================================================================
#ifdef WIN32
	 class Win32PerformanceCounter
	 {
	 public:
		  Win32PerformanceCounter()
		  {
				// Get the "ticks per second" value.
				QueryPerformanceFrequency((LARGE_INTEGER*)(&m_frequency));

				// Convert it into a "ticks per millisecond" value.
				m_frequency = m_frequency / 1000;
		  }

		  // This is the frequency of the performance counter, in "ticks per millisecond"
		  sint64 m_frequency;
	 };

	 Win32PerformanceCounter g_win32counter;
#endif

	 // ================================================================================================================
	 // These functions get a time value. The Actual meaning of this time is undefined; it is only meant to be relative.
	 // ================================================================================================================
	 sint64 GetTimeMS()
	 {
#ifdef WIN32
		  sint64 t;
		  QueryPerformanceCounter((LARGE_INTEGER*)(&t));
		  return t / g_win32counter.m_frequency;
#else
		  struct timeval t;
		  sint64 s;

		  // Get the time of day.
		  gettimeofday(&t, 0);

		  // Calculate the number of milliseconds represented by the seconds.
		  s = t.tv_sec;
		  s *= 1000;

		  // Calculate the milliseconds now.
		  s += (t.tv_usec / 1000);

		  // Return the value.
		  return s;
#endif
	 }

	 sint64 GetTimeS()
	 {
		  return GetTimeMS() / 1000;
	 }

	 sint64 GetTimeM()
	 {
		  return GetTimeMS() / 60000;
	 }

	 sint64 GetTimeH()
	 {
		  return GetTimeMS() / 3600000;
	 }

	 // ================================================================================================================
	 // This prints a timestamp in 24 hours hh:mm:ss format.
	 // ================================================================================================================
	 std::string TimeStamp()
	 {

		  char str[9];

		  // Get the time, and convert it to struct tm format.
		  time_t a = time(0);
		  struct tm* b = localtime(&a);

		  // Print the time to the string.
		  strftime(str, 9, "%H:%M:%S", b);

		  return str;

	 }


	 // ================================================================================================================
	 // This prints a datestamp in YYYY:MM:DD format.
	 // ================================================================================================================
	 std::string DateStamp()
	 {
		  char str[11];

		  // Get the time, and convert it to struct tm format.
		  time_t a = time(0);
		  struct tm* b = localtime(&a);

		  // Print the time to the string.
		  strftime(str, 11, "%Y.%m.%d", b);

		  return str;

	 }


	 Timer::Timer()
	 {
		  m_starttime = 0;
		  m_inittime = 0;
	 }


	 void Timer::Reset(sint64 p_timepassed)
	 {
		  m_starttime = p_timepassed;
		  m_inittime = GetTimeMS();
	 }

	 sint64 Timer::GetMS()
	 {
		  // Return the amount of time that has elapsed since the timer was initialized, plus whatever starting time the 
		  // timer was given.
		  return (GetTimeMS() - m_inittime) + m_starttime;
	 }

	 sint64 Timer::GetS()
	 {
		  return GetMS() / 1000;
	 }

	 sint64 Timer::GetM()
	 {
		  return GetMS() / 60000;
	 }

	 sint64 Timer::GetH()
	 {
		  return GetMS() / 3600000;
	 }

	 sint64 Timer::GetD()
	 {
		  return GetMS() / 86400000;
	 }

	 sint64 Timer::GetY()
	 {
		  return GetD() / 365;
	 }

	 std::string Timer::GetString()
	 {
		  std::string str;
		  sint64 y = GetY();
		  sint64 d = GetD() % 365;
		  sint64 h = GetH() % 24;
		  sint64 m = GetM() % 60;

		  if (y > 0)
				str += BasicLib::tostring(y) + " years, ";
		  if (d > 0)
				str += BasicLib::tostring(d) + " days, ";
		  if (h > 0)
				str += BasicLib::tostring(h) + " hours, ";

		  str += BasicLib::tostring(m) + " minutes";

		  return str;
	 }
} // End namespace BasicLib 


I'm trying to bring it up to C++11 standards. the localtime_s was the first problem I ran into. I'm open to any improvement suggestions. I'll check out the links you provided in the meantime.
I'm open to any improvement suggestions.


When your function says it's going to return a string, don't try to return something that isn't a string. An array of char is not a string.
Last edited on
> don't try to return something that isn't a string. An array of char is not a string

There is an implicit conversion.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <string>

std::string foo()
{
    const char array_of_char[128] = "constructor (5): http://en.cppreference.com/w/cpp/string/basic_string/basic_string" ; // ntbs
    return array_of_char ;
}

int main()
{
    const std::string str = foo() ;
    std::cout << str << '\n' ;
}

http://coliru.stacked-crooked.com/a/870a59acf7fefb8f


> the localtime_s was the first problem I ran into.

Windows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <string>
#include <ctime>

std::string TimeStamp()
{
    char str[32] {};

    time_t a = time(nullptr);

    struct tm time_info ;

    // localtime_s, Microsoft version (returns zero on success, an error code on failure)
    if( localtime_s( &time_info, &a ) == 0  ) strftime( str, sizeof(str), "%H:%M:%S", &time_info );

    return str;
}

http://rextester.com/NXIF17307
Thanks for the programming update.

bishoposiris, when you say you're going an object of a given type, do so. When you get to the stage of being able to use implicit conversions, you'll know.
JLBorges, your code was a success. Thank you!
Cubbi, I'll update to a better system later. Thank you for the links.
> I'm trying to bring it up to C++11

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <chrono>
#include <type_traits>

namespace utility
{
    struct timer
    {
         // http://en.cppreference.com/w/cpp/types/conditional
         // http://en.cppreference.com/w/cpp/chrono/high_resolution_clock
         // http://en.cppreference.com/w/cpp/chrono/steady_clock
         using clock_type = std::conditional< std::chrono::high_resolution_clock::is_steady,
                                              std::chrono::high_resolution_clock,
                                              std::chrono::steady_clock >::type ;

         void reset() { start = clock_type::now() ; }

         // http://en.cppreference.com/w/cpp/chrono/duration
         template < typename DURATION > typename DURATION::rep elapsed()
         {
             const auto now = clock_type::now() ;

             // http://en.cppreference.com/w/cpp/chrono/duration/duration_cast
             return std::chrono::duration_cast<DURATION>( now - start ).count() ;
         }

         private: clock_type::time_point start = clock_type::now() ;
    };
}

// usage example:
#include <iostream>

int main()
{
    using namespace std::chrono ;

    utility::timer t ;

    std::cout << "press enter: " && std::cin.get() ;
    std::cout << t.elapsed<milliseconds>() << " milliseconds\n" ;

    t.reset() ;
    std::cout << "\npress enter again: " && std::cin.get() ;
    std::cout << t.elapsed<microseconds>() << " microseconds\n" ;

    t.reset() ;
    std::cout << "\npress enter a last time: " && std::cin.get() ;
    std::cout << t.elapsed<nanoseconds>() << " nanoseconds\n" ;
}
More C++14:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <string>
#include <chrono>
#include <sstream>
#include <iomanip>
#include <ctime>

template < typename CLOCK_TYPE = std::chrono::system_clock >
std::string time_stamp( const typename CLOCK_TYPE::time_point& time_point, const std::string& format = "%F %T %Z (UTC%z)" )
{
    const std::time_t t = CLOCK_TYPE::to_time_t(time_point);
    const std::tm tm = *std::localtime( std::addressof(t) ) ;

    std::ostringstream stm ;
    stm << std::put_time( std::addressof(tm), format.c_str() ) ;
    return stm.str() ;
}

std::string time_stamp() { return time_stamp( std::chrono::system_clock::now() ) ; }

int main()
{
     std::cout << "    now: " << time_stamp() << "\n    now: " << time_stamp( std::chrono::system_clock::now(), "%A %T") << '\n' ;

     using namespace std::literals ;

     // 80 hours, 18 minutes, 42 seconds earlier
     const auto earlier = std::chrono::system_clock::now() - 80h - 18min - 42s ;
     std::cout << "earlier: " << time_stamp(earlier) << '\n' ;

     // 27 minutes, 30 seconds later
     const auto later = std::chrono::system_clock::now() + 27min + 30s ;
     std::cout << "  later: " << time_stamp(later) << '\n' ;
}

http://rextester.com/HADNXK16356
http://coliru.stacked-crooked.com/a/d56d9900c42e4209
Topic archived. No new replies allowed.