Get System Date Format String Win32 - c++

I need to get the system current date format string like ("dd-mm-yyyy" , "mm/dd/yyyy" ect.
GetDateFormat() API returns the formatted string like "12-09-2015" but need string like "dd-mm-yyyy"
C# solution
string sysFormat = CultureInfo.CurrentCulture.DateTimeFormat.ShortDatePattern;
But I need in Win32.

You can get a list of format strings currently applicable, by enumerating them. This is done through EnumDateFormats. Note, that there can be (and usually is) more than one, so you will have to decide, which one to pick1).
The following code returns the system's default short dateformat pattern:
static std::list<std::wstring> g_DateFormats;
BOOL CALLBACK EnumDateFormatsProc( _In_ LPWSTR lpDateFormatString ) {
// Store each format in the global list of dateformats.
g_DateFormats.push_back( lpDateFormatString );
return TRUE;
}
std::wstring GetShortDatePattern() {
if ( g_DateFormats.size() == 0 &&
// Enumerate all system default short dateformats; EnumDateFormatsProc is
// called for each dateformat.
!::EnumDateFormatsW( EnumDateFormatsProc,
LOCALE_SYSTEM_DEFAULT,
DATE_SHORTDATE ) ) {
throw std::runtime_error( "EnumDateFormatsW" );
}
// There can be more than one short date format. Arbitrarily pick the first one:
return g_DateFormats.front();
}
int main() {
const std::wstring strShortFormat = GetShortDatePattern();
return 0;
}
1) The .NET implementation does the same thing. From its list of candidates, it arbitrarily picks the first one.

You can use time function together with localtime function.
Example code:
//#include <time.h>
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
//The years are since 1900 according the documentation, so add 1900 to the actual year result.
char cDate[255] = {};
sprintf(cDate, "Today is: %d-%d-%d", timeinfo->tm_mday, timeinfo->tm_mon, timeinfo->tm_year + 1900);

Related

How to add 1 hour to 8601 format time string in C++ on Windows?

I've got an 8601 format time string like so:
std::string strTime("1601-01-01T00:01:53.537Z");
I want to increment the hour and change its value to
"1601-01-01T01:01:53.537Z"
I think the steps are: convert string to a time object, increment the hour by 1, convert the object back to a string.
Of course, it would be helpful if all the normal time considerations and boundaries were taken into account (such as adding an hour to 11:30 pm will move to the next day, etc...). I've been looking at strftime, strptime, std::get_time and others but have not been able to work it out yet.
I'm using VS2012 on Windows. Thanks.
Some pseudo code to get you started.
char *AddHour(char *dest, size_t size, const char *timestamp) {
Initialize struct tm
Scan timestamp into tm
Check scanning success
Check year range validity
Bring into range acceptable by mktime()
Add hour
Call mktime()
Undo range adjustment made beforehand
Print tm to dest
return dest;
}
Even though mktime() uses local timezone, by keeping the tm_isdst == 0 we can use this for the Z timezone (UTC) for all practical purposes.
Simply scan the string into various parts. Add 1 hour and then reform the string
string --> struct tm tm;
// Add hour
if (++tm.tm_hour >= 24) {
tm.tm_hour = 0;
if (++tm.tm_mday > EOM(tm.tm_year, tm.tm_mon)) {
tm.tm_mday = 1;
if (++tm.tm_mon > 12) {
tm.tm_mon = 1;
tm.tm_year++;
}
}
}
struct tm tm --> string
I have written a C library that parses and formats a ISO 8601 calendar date with time and zone designator in extended format. It's available on Github, c-timestamp.
{
timestamp_t ts;
char *str = "1601-01-01T00:01:53.537Z";
timestamp_parse(str, strlen(str), &ts);
ts.sec += 1*60*60;
timestamp_format(str, strlen(str), &ts);
puts(str);
}

Library calls for converting timestruc_t to text or struct tm

I was writing a quick utility to dump out some of the details of the stat structure but hit an issue as the time attributes of stat seem to be of type timestruc_t which on my platform seems to be two 64bit ints.
struct stat statBuf;
return_code = stat( aFileName, &statBuf );
if ( !return_code )
{
struct tm res;
localtime_r( statBuf.st_mtim.tv_sec, &res ); // problem!
I thought I could maybe use localtime_r to convert the seconds attribute into a struct tm but I seem to get casting issues using statBuf.st_mtim.tv_sec as the first parameter.
I'm sure this isn't the best solution - maybe you know a better one. I just want to get the date and time - down to sub-seconds if possible - out as a string in the format YYYY-MM-DD HH.MM.SS.SSS or something similar. Any suggestions would be very welcome.
UPDATE
This was a simple issue - my mistake. Just forgot that the first parameter needs to be the address of and int not the int by value. So the amended and partially completed code looks like this:
localtime_r( &statBuf.st_mtim.tv_sec, &res );
const int bufLen=24;
char buffer[ bufLen + 1];
strftime( buffer, bufLen, "%Y-%m-%d %H:%M:%S", &res );
printf(" %s, %s\n", aFileName, buffer);
The first parameter needs to be the address of an int not the int by value.

Build string as in printf function

printf("%d.%d.%d", year, month, day);
Can I do the same but without printing, smth like
char* date = "%d.%d.%d", year, month, day;
Or maybe some other simple ways to do that?
In plain c there is asprintf() which will allocate memory to hold the resulting string:
#include <stdio.h>
char *date;
asprintf(&date, "%d.%d.%d", year, month, day);
(error handling omitted)
Since you have tagged C++ you probably want to use the C++ solutions.
In C++:
#include <string>
std::string date = std::to_string(year) + '.' +
std::to_string(month) + '.' + std::to_string(day);
If you need the underlying char const *, say date.c_str().
The function std::to_string uses snprintf internally; you should probably look up that function, too, as it is fairly fundamental to formatted output, and you can use it directly if you really think you need to.
There are various implementations of a format function that looks something like:
std::string format(const std::string& fmt, ...);
so your example would be:
std::string date = format("%d.%d.%d", year, month, day);
One possible implementation is shown below.
Boost has a format library that works a little differently. It assumes you like cin, cout, and their ilk:
cout << boost::format("%1%.%2%.%3%") % year % month % day;
Or, if you just wanted a string:
boost::format fmt("%1%.%2%.%3%");
fmt % year % month % day;
std::string date = fmt.str();
Note that % flags are not the ones you're used to.
Finally, if you want a C string (char*) instead of a C++ string, you could use the asprintf function:
char* date;
if(asprintf(&date, "%d.%d.%d", year, month, day) == -1)
{ /* couldn't make the string; format was bad or out of memory. */ }
You could even use vasprintf to make your own format function returning a C++ string:
std::string format(const char* fmt, ...)
{
char* result = 0;
va_list ap;
va_start(ap, fmt);
if(vasprintf(*result, fmt, ap) == -1)
throw std::bad_alloc();
va_end(ap);
std::string str_result(result);
free(result);
return str_result;
}
This isn't terribly efficient, but it works. There also might be a way to call vsnprintf twice, the first with no buffer to get the formatted string length, then allocate the string object with the right capacity, then call the second time to get the string. This avoids allocating the memory twice, but has to make two passes through the formatted string.
In C++ I wrote a function to create strings using the printf format.
Headerfile stringf.h:
#ifndef STRINGF_H
#define STRINGF_H
#include <string>
template< typename... argv >
std::string stringf( const char* format, argv... args ) {
const size_t SIZE = std::snprintf( NULL, 0, format, args... );
std::string output;
output.resize(SIZE+1);
std::snprintf( &(output[0]), SIZE+1, format, args... );
return std::move(output);
}
#endif
Usage:
#include "stringf.h"
int main(){
int year = 2020;
int month = 12;
int day = 20
std::string date = stringf("%d.%d.%d", year, month, day);
// date == "2020.12.20"
}
In C language use sprintf function from stdio.h header file.
char buffer[100];
sprintf(buffer,"%d.%d.%d", year, month, day);
See here for more info.

Splitting a `char[]` in C++

I have a char[] in YYYYMMDDHHMMSS format.
e.g. 2011052504572
I want to retrieve the year, month, date, hour, minute and second from this char. How do I do that?
NOTE:I cant use any third party dll.
Thanks,
Syd
If you're using the STL then just put the string into a std::string and use the substr method:
std::string dateTime=......;
std::string year=dateTime.substr(0,4);
std::string month=dateTime.substr(4,2);
// etc
// etc
Use string::substr() for this purpose. Example,
string date = "20110524112233";
string year = date.substr(0, 4);
string month = date.substr(4, 2);
string day = date.substr(6, 2);
string hour = date.substr(8, 2);
string minute = date.substr(10, 2);
string second = date.substr(12, 2);
It depends on whether you want to extract the values as text, or convert them to numbers. For getting lots of strings, you can use std::string and substr() as thoroughly illustrated in other answers.
If you want to get numbers that you can then calculate with, then one approach is:
int year, month, day, hour, minute, second;
if (sscanf(input, "%.4d%.2d%.2d%.2d%.2d%.2d",
&year, &month, &day, &hour, &minute, &second) == 6)
{
// all 6 conversions worked... can use the values...
int second_in_day = hour * 3600 + minute * 60 + second;
...
}
Another approach is to use strptime() - if your system has it. It parses a string into a broken-down-time structure:
struct tm tm;
strptime(input, "%Y%m%d%H%M%S", &tm);
// parsed values are in tm.tm_year, tm.tm_mon, tm.tm_mday,
// tm.tm_hour, tm.tm_min, tm.tm_sec
// further, tm_wday has day of week, tm_yday has day in year
// i.e. it actually understands the date, not just chopping up numbers/text
Note: sscanf() and strncpy() are C functions callable from C++, and they're not as safe to use as C++-specific functionality (std::string, std::istringstream) in that small misunderstandings and mistakes in handling the data can lead to not just erroneous results, but program crashes. So, read the manual pages for these things carefully if you use them.
Use strncpy... okay, so if it is not homework, then this is the best way. The others using std::string are wasting resources:
static const char *yyyymmddhhmmss = "20110526101559";
char year[5] = { '\0' };
char month[3] = { '\0' };
char day[3] = { '\0' };
char hour[3] = { '\0' };
char minute[3] = { '\0' };
char second[3] = { '\0' };
strncpy(year, yyyymmddhhmmss, 4);
strncpy(month, &yyyymmddhhmmss[4], 2);
strncpy(day, &yyyymmddhhmmss[6], 2);
strncpy(hour, &yyyymmddhhmmss[8], 2);
strncpy(minute, &yyyymmddhhmmss[10], 2);
strncpy(second, &yyyymmddhhmmss[12], 2);
Since you have the input in the form of a char[] (or char*—for
this use, it comes out to the same thing), the simplest solution is
probably using the two iterator constructors for std::string to creat
a string for each field, e.g.:
std::string year ( date , date + 4 );
std::string month( date + 4, date + 6 );
std::string day ( date + 6, date + 8 );
// ...
If you need the numerical values, boost::lexical_cast can be used,
e.g.:
int extractField( char const* string, int begin, int end )
{
return boost::lexical_cast<int>(
std::string( date + begin, date + end ) );
}
int year = extractField( date, 0, 4 );
int year = extractField( date, 4, 6 );
// ...

Get File Last Modify Time and Compare

I want a piece of function which will take a file and last how many days, if it was older than that date, will return 0 otherwise 1... Something like that...
For example:
int IsOlder(TCHAR *filename, int days)
{
do operation.
If last modify date was older than days variable
return 0
else
return 1
}
It's MS VC++ 6 for Windows.
Thanks from now!
Windows has an API function called GetFileTime() (doc on MSDN) taking a file handle in parameter and 3 FILETIME structures to be filled with date-time info:
FILETIME creationTime,
lpLastAccessTime,
lastWriteTime;
bool err = GetFileTime( h, &creationTime, &lpLastAccessTime, &lastWriteTime );
if( !err ) error
The FILETIME structure is obfuscated, use the function FileTimeToSystemTime() to translate it to a SYSTEMTIME structure which is way easier to use:
SYSTEMTIME systemTime;
bool res = FileTimeToSystemTime( &creationTime, &systemTime );
if( !res ) error
Then you can use fields wYear, wMonth, etc. to compare with your number of days.
GetFileTime gets the various dates relevant to a file. There's an example.
You will need to fetch the last write time, and calculate the difference in days from there. As the GetFileTime function returns the quite unwieldy FILETIME structure you probably want to convert it into system time (struct SYSTEMTIME) with FileTimeToSystemTime.