How to use fromString() with currentDate() - c++

I'm trying to get current date from the system clock and change its format (i.e. to this format dd/MM/yyyy). After that I need to set QDateEdit using setDate(). My problem is that using fromString() with QDate::currentDate() returns an invalid date. This is the piece of code regarding this issue
QDate date = QDate::currentDate().fromString("dd/MM/yyyy");
qDebug() << date.toString(); // <-- returns empty string
StartDateEdit->setDate(date); // <-- adding invalid date shows 1-1-2000
My system clock has this format M/d/yyyy in Windows 10. Any suggestions?

QDate::currentDate() is a static function, this returns the current date, the object stores the date, not the format. If you want to display the form: "dd/MM/yyyy" you must use the setDisplayFormat function of QDateEdit.
QDate date = QDate::currentDate();
StartDateEdit->setDate(date);
StartDateEdit->setDisplayFormat("dd/MM/yyyy");
Note:The fromString function converts a string to QDate indicating the format of the string.

Related

Unreliable DateTime parsing by COleDateTime

I am trying to parse the date using ParseDateTime method provided by COleDateTime class. But parsing of two different dates in the same program is returning inconsisent values for the month.
Code Snippet:
COleDateTime dtCreated;
dtCreated.ParseDateTime(safe_cast<CString>(strCreatedDate));
Inconsistent RESULTS:
if strCreatedDate = "10/7/2020" (in mm.dd.yyyy format)
then dtCreated.GetMonth() = 7 (but it should be 10)
if strCreatedDate = "7/29/2020" (in mm.dd.yyyy format)
then dtCreated.GetMonth() = 7 (in this case, it is correct)
UPDATE:
The value of date present in the strCreatedDate vairable could be "dd.mm.yyyy" OR "mm.dd.yyyy" format. But I do have the information about the data format available in a separate variable. Based on the format, I want COleDateTime to correctly parse the DateTime string. How can I do that?
Since String^ is your input you could use DateTime::ParseExact, and then convert DateTime to COleDateTime using DateTime.ToOADate:
COleDateTime dtCreated(DateTime::ParseExact(
strCreatedDate, isDMY ? "d.M.yyyy" : "M.d.yyyy", nullptr).ToOADate());

Getting COleDateTime::Format to return "stycznia" instead of "styczeń" for Polish month "January"

I have this method to set the locale to Polish:
void CMeetingScheduleAssistantApp::SetLocale()
{
// https://www.microsoft.com/resources/msdn/goglobal/default.mspx#ISO2
CString strLang[NUM_LANGUAGES] =
{
_T("plk")
// Add more languages here
};
_tsetlocale(LC_ALL, strLang[m_eLanguage - LANGUAGE_ENGLISH]);
}
I have cut the other languages out for brevity. Now, when I format a COleDateTime object and display the month, say January, it shows as:
styczeń
But i want to show it as:
stycznia
Is there a locale setting to adjust the month values returned by the COleDateTime::Format method or locale?
Otherwise I will have to add something manual to override.
The months I would like returned are:
stycznia
lutego
marca
kwietnia
maja
czerwca
lipca
sierpnia
września
października
listopada
grudnia
Update
According to here it states:
Some languages, such as Finnish, German, Polish, and Russian, have
several noun forms. If you plan to use localized names provided by the
system, have a linguist check to make sure you are using them in the
right context. Windows carries both the nominative and genitive forms
of Polish and Russian month names; the form changes depending on
the month name's position in the string relative to the day name.
Windows returns both forms in a single string separated by a null
value. The system carries only one form of each month name or day
name for all other languages.
Now, this is how I am actually formatting my date strings (since I am supporting over 40 languages it is a bit tricky. So, (for English) I start with this format string:
%1 %2!d!-%3!d!
%1 is the month.
%2!d! is the first day value.
%3!d! is the second day value.
If my date needs to cater for crossing over two months, I have:
%1 %2!d!–%3 %4!d!
%1 is the month value.
%2!d! is the first day value.
%3 is the second month value.
%3!d! is the second day value.
The above is used like this:
if (datThisMonday.GetMonth() == datEndOfWeek.GetMonth())
{
strDate.FormatMessage(IDS_STR_TPL_OCLM_WEEK,
datThisMonday.Format(_T("%B")), datThisMonday.GetDay(), datEndOfWeek.GetDay());
}
else
{
strDate.FormatMessage(IDS_STR_TPL_OCLM_WEEK2,
datThisMonday.Format(_T("%B")), datThisMonday.GetDay(),
datEndOfWeek.Format(_T("%B")), datEndOfWeek.GetDay());
}
For Polish, my respective format strings are:
%2!d!-%3!d! %1
%2!d! %1–%4!d! %3
So, I can see that because I am formatting the the date string using FormatMessage and only using the COleDateTime::Format method to parse just the month that it is potentially the cause of the issue.
Since I have two dates in the date string I can't just use a single Date formatting API call (since my date string is representing a week span).
So I checked:
strDate = datThisMonday.Format(_T("%d %B"));
And it made no difference. So I tried this instead:
SYSTEMTIME sTime;
datThisMonday.GetAsSystemTime(sTime);
GetDateFormat(GetThreadLocale(),
DATE_LONGDATE,
&sTime, _T("d MMMM"),
strDate.GetBuffer(_MAX_PATH), _MAX_PATH);
It made no difference. It still shows the date the same way as before. Even if it did display the date correctly it doesn't factor for a date range from two COleDateTime objects.
Confused.
Update 2:
Also tried:
TCHAR szDate[100] = _T("");
GetDateFormatEx(_T("pl"), NULL, &sTime, _T("ddd MMMM"), szDate, 100, NULL);
AfxMessageBox(szDate);
Just will not show the variant.
Update 3
The only way I can get it to show the right date is like this:
GetDateFormatEx(_T("pl"), DATE_LONGDATE, &sTime, NULL, szDate, 100, NULL);
Then the month is correct. Now in the article I referred to it states:
Windows returns both forms in a single string separated by a null
value.
I can't even work out how to access that.
I have encountered other issues but they are distinct from this question, so I will still provide my answer here.
Firstly, I found a document which states that you must have d in the date for it to show the correct version of the month.
Since, I am wanting to display a date range, I start with this:
Polish
Template: %1-%2
Date 1: d
Date 2: d MMMM
Then I format the date:
SYSTEMTIME sysTime;
ENSURE(rDate.GetAsSystemTime(sysTime));
GetDateFormatEx(_T("pl"),
NULL,
&sysTime,
strDateFormat,
strDate.GetBuffer(_MAX_PATH), _MAX_PATH, nullptr);
That displays it correctly. And if the date range spans two months I have:
Template: %1-%2
Date 1: d MMMM
Date 2: d MMMM
It works well.
Since Windows 7, you can also use the LOCALE_RETURN_GENITIVE_NAMES to return the genitive name of a month. Running this :
const wchar_t localeName[] = L"pl-PL";
for (LCTYPE m = LOCALE_SMONTHNAME1; m <= LOCALE_SMONTHNAME12; ++m) {
wchar_t buf[1024];
GetLocaleInfoEx(localeName, m | LOCALE_RETURN_GENITIVE_NAMES, buf, sizeof(buf) / sizeof(*buf));
std::cout << to_utf8(buf) << '\n';
}
Gives the following result :
stycznia
lutego
marca
kwietnia
maja
czerwca
lipca
sierpnia
września
października
listopada
grudnia
which are indeed proper genitive names for months in Polish.

C++ , using strptime and strftime to convert date formats including invalid dates

Am using strptime and strftime to convert date from one format to another in C++,
Everything works fine for valid input dates but in case of invalid dates it just can't work.
Using mktime 'fixes' or changes dates like if there is an invalid day, it automatially changes the month as well. What I want is to convert any input date from one format to another like
if it is 12/22/99 and i want to convert from mm/dd/yy to dd-mm-yyyy, it shall convert to 22-12-1999.
If there is any invalid date, it shall emit 00 and keep the other things in required format, like 12/45/01 (in mm/dd/yy) shall convert to 00-12-2001 (in dd/mm/yyyy format since day can't be 45), the problem is strptime, mktime, all changes the value since the tm timestruct works that way, is there any possibility to do that?
A simple use case can be
convert mm/dd/yy to dd-mm-yyyy
03/33/99 -> 00-03-1999
I tried my best but strptime just changes the corresponding month in case of a wrong input day. I tried putting 00 in case of a wrong date, but strptime handles 00 differently too, so for each format, it can't work. Really stuck now.
////////////////////////////////////////////
// For those who wants a programming question
// i repeat, it is a programming question
/////////////////////////////////////////////
struct tm timestruct = {0};
// it can be in any other supported format as well
char *in = "80-00-11";
string fromStr("%Y-%d-%m ");
string toStr("%d/%m/%y");
char buf[255];
if(strptime(in, fromStr.c_str(), &timestruct) == NULL ) // invalid date
strftime(buf, sizeof(buf), toStr.c_str(), &timestruct);
puts(buf);
/* The problem is in case of wrong date like the supplied date in char *in.
i want to leave out the correct parameters of the supplied data, like
00/**11/98**, but it changes the **11** to some other value, my problem is i may have day as empty field like given in the code snippet
*/

QDateTime::fromString returns invalid Date, what am I missing?

I have some code that reads a datetime from a sqlite database, the datetime is returned as a string. when I try to convert it to a date using QDateTime::FromString it returns an invalid date. Below is the time as returned from the database and conversion.
Why is this failing to parse?
// -this is the value returned from the DB currentServerTime=2012-01-17 19:20:27.0
QString format("yyyy/MM/dd hh:mm:ss");
QString qCurrentServerTime(currentServerTime);
now = QDateTime::fromString(qCurrentServerTime, format);
No expert in QT, but if QDateTime::fromString() works as one would (reasonably) expect and according to this, you're not using the correct pattern.
You indicate the string read from the sqllite database is like "2012-01-17 19:20:27.0", then your format should be like yyyy-MM-dd HH:mm:ss.z.
In detail:
Your separator should by '-' not '/' (as you show in the example)
The time seems to be in 24 hours format (19 -> 7 p.m.) (so use HH instead of hh)
You have one digit for milliseconds, so add .z.

C++ boost date format

I have a vector string of dates in the from "dd-mmm-yyyy" so for example
todays date would be:
std::string today("07-Sep-2010");
I'd like to use the date class in boost but to create a date object the
constructor for date needs to be called as follows:
date test(2010,Sep,07);
Is there any easy/elegant way of passing dates in the format "dd-mmm-yyyy"?
My first thought was to use substr and then cast it? But I've read that there's also
the possibility of using 'date facets'?
Thanks!
include "boost/date_time/gregorian/parsers.hpp"
date test = boost::gregorian::from_us_string("07-Sep-2010")
There is a builtin parser for this form of date in Boost itself, check out the docs here:
http://www.boost.org/doc/libs/1_44_0/doc/html/date_time/date_time_io.html#date_time.io_objects
date_type parse_date(...)
Parameters:
string_type input
string_type format
special_values_parser
Parse a date from the given input using the given format.
string inp("2005-Apr-15");
string format("%Y-%b-%d");
date d;
d = parser.parse_date(inp,
format,
svp);
// d == 2005-Apr-15
with inp adjusted for your needs.