"2009-01-23T11:57:26-06:00"
Thanks.
I don't know if there exists a function to do that out of the box.
However, it should not be difficult to write one by yourself.
As guidelines, I would parse the given string and set the fields of a
SYSTEMTIME structure.
(Parsing that string is easy because it seems to me that the above string
fields are of fixed length, so you can just use constant integer indexes
into the string array to get the beginning and the end of each substring).
SYSTEMTIME Structure
http://msdn.microsoft.com/en-us/library/ms724950.aspx
Then, I would call SystemTimeToFileTime() API to convert that to a FILETIME:
SystemTimeToFileTime Function
http://msdn.microsoft.com/en-us/library/ms724948.aspx
HTH,
Giovanni
"Michael Tissington" <nos...@nospam.com> ha scritto nel messaggio
news:%23VdQ%23ADgJ...@TK2MSFTNGP06.phx.gbl...
> How can I parse the following string as a FILETIME ?
>
> "2009-01-23T11:57:26-06:00"
To add to what I previously wrote, unfortunately in this string there is a
specification of a time zone (e.g. "-06:00").
I've never done that with pure C++; however I've found that the .NET
framework offers very convenient classes (as usual!) to do this kind of
conversion and for parsing a string in the format you requested.
So, I developed a small C++/CLI routine to do that job. It uses the
System.DateTime.ParseExact() method to parse the input string, and the
System.DateTime.ToFileTime() method to convert the resulting DateTime object
to a Windows file time (represented as __int64).
I used this string to map your string format: "yyyy-MM-ddTHH:mm:sszzz" (note
the trailing "zzz" characters that represent the time zone specification).
<code language="C++/CLI">
/// <summary>
/// Converts a UTC date time string in a Windows file time.
/// </summary>
/// <param name="utc">Input string in UTC format, e.g.
2009-01-23T11:57:26-06:00</param>
/// <returns>The Windows file time corresponding to the input
string.</returns>
/// <exception cref="System.FormatException">When input string format is
wrong.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">The resulting file
time would represent
/// a date and time before 12:00 midnight January 1, 1601 C.E.
UTC.</exception>
__int64 UTCDateTimeToFileTime(String^ utc)
{
// Parse input string
String^ expectedFormat = "yyyy-MM-ddTHH:mm:sszzz";
System::DateTime ^ resultDateTime = System::DateTime::ParseExact(
utc,
expectedFormat,
System::Globalization::CultureInfo::InvariantCulture
);
// Convert it to Windows file time
return resultDateTime->ToFileTime();
}
</code>
You can use this function in code like this:
<code language="C++/CLI">
// *** TEST ***
int main(array<System::String ^> ^args)
{
String^ inputDate = "2009-01-23T11:57:26-06:00";
try
{
Console::WriteLine("{0} corresponds to file time {1}.",
inputDate, UTCDateTimeToFileTime(inputDate));
}
catch (System::FormatException^ ex)
{
Console::WriteLine("Error in parsing date time string:");
Console::WriteLine(ex->Message);
}
return 0;
}
</code>
The beauty of the C++/CLI extensions is that you can use the powerful and
rich .NET Framework library into C++ code.
I don't know if there is something "pure native" (i.e. not in the .NET
Framework, just pure native C++ code) to do that, but I've not found
anything (e.g. it seems to me that ATL/MFC class CTime does not support time
zone conversion...).
For the sake of completeness, I report the C# function I developed in the
beginning (in fact, I developed the C# function first, and then converted it
to C++/CLI - in fact, C# is more "natural" language to develop for the .NET
framework, IMHO):
<code language="C#">
/// <summary>
/// Converts a UTC date time string in a Windows file time.
/// </summary>
/// <param name="utc">Input string in UTC format, e.g.
2009-01-23T11:57:26-06:00</param>
/// <returns>The Windows file time corresponding to the input
string.</returns>
/// <exception cref="System.FormatException">When input string format is
wrong.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">The resulting file
time would represent
/// a date and time before 12:00 midnight January 1, 1601 C.E.
UTC.</exception>
static public long UTCDateTimeToFileTime(string utc)
{
// Parse input string
string expectedFormat = "yyyy-MM-ddTHH:mm:sszzz";
DateTime resultDateTime = DateTime.ParseExact(utc, expectedFormat,
CultureInfo.InvariantCulture);
// Convert it to Windows file time
return resultDateTime.ToFileTime();
}
</code>
And this is a working C# program to test that:
<code language="C#">
//////////////////////////////////////////////////////////////////////////
/// Shows how to convert an UTC date time to a Windows file time.
///
/// by Giovanni Dicanio
//////////////////////////////////////////////////////////////////////////
using System;
using System.Globalization;
namespace ConsoleApplication1
{
class Program
{
/// <summary>
/// Converts a UTC date time string in a Windows file time.
/// </summary>
/// <param name="utc">Input string in UTC format, e.g.
2009-01-23T11:57:26-06:00</param>
/// <returns>The Windows file time corresponding to the input
string.</returns>
/// <exception cref="System.FormatException">When input string
format is wrong.</exception>
/// <exception cref="System.ArgumentOutOfRangeException">The
resulting file time would represent
/// a date and time before 12:00 midnight January 1, 1601 C.E.
UTC.</exception>
static public long UTCDateTimeToFileTime(string utc)
{
// Parse input string
string expectedFormat = "yyyy-MM-ddTHH:mm:sszzz";
DateTime resultDateTime = DateTime.ParseExact(utc,
expectedFormat, CultureInfo.InvariantCulture);
// Convert it to Windows file time
return resultDateTime.ToFileTime();
}
// *** Test ***
static void Main(string[] args)
{
string inputDate = "2009-01-23T11:57:26-06:00";
try
{
Console.WriteLine("{0} corresponds to file time {1}.",
inputDate, UTCDateTimeToFileTime(inputDate));
}
catch (System.FormatException ex)
{
Console.WriteLine("Error in parsing date time string:");
Console.WriteLine(ex.Message);
}
return;
}
}
}
</code>
HTH,
Giovanni
I'm not sure if it is as easy as with .NET, but if you have a need of having
100% native C++ code and no dependecies with .NET framework, I found this
from Boost, that might help:
http://www.boost.org/doc/libs/1_37_0/doc/html/date_time/date_time_io.html
Giovanni
http://msdn.microsoft.com/en-us/library/38wh24td(VS.80).aspx
It has some cool parsing functionality.
Tom
"Michael Tissington" <nos...@nospam.com> wrote in message
news:%23VdQ%23ADgJ...@TK2MSFTNGP06.phx.gbl...
I've not used it, but does it support time zone specification?
Thanks,
Giovanni
CTime MyApp::ConvertUTCDateTime(LPCTSTR szDateTime)
{
// Parse the start date from format 2008-04-03T16:03:52+08:00
CString cs = szDateTime;
int i = cs.Find(_T('T'));
if(i != -1) {
CString csDate = cs.Left(i);
CString csTime = cs.Mid(i+1);
i = csTime.ReverseFind(_T('+'));
if(i == -1)
i = csTime.ReverseFind(_T('-'));
else {
// Use GMT?
csTime = csTime.Left(i);
}
cs.Format(_T("%s %s"),csDate,csTime);
COleDateTime oTime;
if(oTime.ParseDateTime(cs)) {
SYSTEMTIME sTime;
oTime.GetAsSystemTime(sTime);
return CTime(sTime);
}
}
return CTime::GetCurrentTime();
}
It workerd for me and I think the ParseDateTime() functions accepts a lot of
different date/time formats so it's pretty handy.
Tom
"Giovanni Dicanio" <giovanniD...@REMOVEMEgmail.com> wrote in message
news:uAnOsaKg...@TK2MSFTNGP04.phx.gbl...
> Here is a routine I used to convert a date I had:
>
> CTime MyApp::ConvertUTCDateTime(LPCTSTR szDateTime)
> {
> // Parse the start date from format 2008-04-03T16:03:52+08:00
[...]
Tom: analyzing your code, I think that this code is missing the time zone
specification (e.g. +08:00) in the conversion.
Of course, I can be wrong, so please correct me if I am missing something
(it's also late here :)
I tried your routine with the addition of this code (beacuse the OP
requested a conversion to FILETIME):
<code>
LPCTSTR szInputDate = _T("2009-01-23T11:57:26-06:00");
CTime t = Tom::ConvertUTCDateTime(szInputDate);
SYSTEMTIME sysTime;
ATLVERIFY(t.GetAsSystemTime(sysTime));
FILETIME fileTime;
SystemTimeToFileTime(&sysTime, &fileTime);
</code>
And I compared that with the routine I proposed (using C++/CLI and .NET
System.DateTime.ParseExact with proper format string):
<code>
__int64 UTCDateTimeToFileTime(String^ utc)
{
// Parse input string
String^ expectedFormat = "yyyy-MM-ddTHH:mm:sszzz";
System::DateTime ^ resultDateTime = System::DateTime::ParseExact(
utc,
expectedFormat,
System::Globalization::CultureInfo::InvariantCulture
);
// Convert it to Windows file time
return resultDateTime->ToFileTime();
}
</code>
and it seems to me that we get two different results.
e.g. with the input string:
2009-01-23T11:57:26-06:00
my routine returns this 64-bit integer value for FILETIME:
0x1c97d840cc28700
instead yours returns this:
0x1c980d29222a000
I can be wrong, but my idea is that your code is not considering the time
zone specification.
Actually, I kind of hope that I am wrong :) because your code has the
advantage of being pure C++ and not depending on .NET framework classes.
Thanks,
G
CTime Mycode::ConvertUTCDateTime(LPCTSTR szDateTime)
{
// Parse the start date from format 2008-04-03T16:03:52+08:00
CString cs = szDateTime;
int i = cs.Find(_T('T'));
if(i != -1) {
CString csDate = cs.Left(i);
CString csTime = cs.Mid(i+1);
i = csTime.ReverseFind(_T('+'));
if(i == -1) {
i = csTime.ReverseFind(_T('-'));
}
if(i != -1) {
Isn't this a time value that has to be subtracted from the "16:03:52" to
arrive at the UTC ?
Yes, but probably subtle cases should be considedered.
For example: if you do the subtraction, and you get a negative number, then
it means that you should update also the day (i.e. you are on the previous
day).
But that would mean that you may check also the month value that could
change (e.g. when passing from 1 February to January 31th). And probably a
consideration about years having February with 28 days vs. 29 days should be
done, too.
(And I'm not sure if daylight time considerations should be made....)
This is why I proposed to give that job to an "out of the box" method like
System.DateTime.ParseExact().
Giovanni
>Here is a routine I used to convert a date I had:
>
>CTime MyApp::ConvertUTCDateTime(LPCTSTR szDateTime)
>{
> // Parse the start date from format 2008-04-03T16:03:52+08:00
> CString cs = szDateTime;
> int i = cs.Find(_T('T'));
> if(i != -1) {
> CString csDate = cs.Left(i);
> CString csTime = cs.Mid(i+1);
> i = csTime.ReverseFind(_T('+'));
> if(i == -1)
> i = csTime.ReverseFind(_T('-'));
> else {
> // Use GMT?
> csTime = csTime.Left(i);
> }
> cs.Format(_T("%s %s"),csDate,csTime);
> COleDateTime oTime;
> if(oTime.ParseDateTime(cs)) {
> SYSTEMTIME sTime;
> oTime.GetAsSystemTime(sTime);
> return CTime(sTime);
> }
> }
> return CTime::GetCurrentTime();
>}
In the old days we'd simply written
int year, month, day;
int hour, minute, second;
int tz_hour, tz_minute;
char *p = "2009-01-23T11:57:26+06:00";
sscanf(p, "%d-%d-%dT%d:%d:%d%d:%d",
&year, &month, &day,
&hour, &minute, &second,
&tz_hour, &tz_minute );
That works with positive as negative TZ values as well. I'm not sure
about an official definition of that string format. If there are
differences it would fail. sscanf() is deprecated and there is also
unicode these days, so sscanf_s() or swscanf_s() would be the choice
today.
Hans
Tom
"Hans-J. Ude" <ne...@s237965939.online.de> wrote in message
news:gfb0o4po27a8t26a5...@4ax.com...
modify your FILETIME result by 600,000,000 ticks per second timediff
and you're done ;-)
I think there could be subtle cases, too.
As I wrote already in this thread:
<cite>
Yes, but probably subtle cases should be considedered.
For example: if you do the subtraction, and you get a negative number, then
it means that you should update also the day (i.e. you are on the previous
day).
But that would mean that you may check also the month value that could
change (e.g. when passing from 1 February to January 31th). And probably a
consideration about years having February with 28 days vs. 29 days should be
done, too.
(And I'm not sure if daylight time considerations should be made....)
</cite>
Giovanni
> I think there could be subtle cases, too.
My bad, you are right .rhavin!
We can do the subtraction from FILETIME (__int64).
Thanks,
Giovanni
I think that this idea of subtracting an amount based from time zone
difference from FILETIME value is good; probably you have nailed the problem
:)
Thanks,
Giovanni
SYSTEMTIME st = {0};
LONG ltzHour;
LONG ltzMinute;
ULONGLONG ull;
sscanf(psz, "%d-%d-%dT%d:%d:%d%d:%d", &st.wYear, &st.wMonth, &st.wDay,
&st.wHour, &st.wMinute, &st.wSecond, <zHour, <zMinute);
SystemTimeToFileTime(&st, (LPFILETIME)&ull);
// Adjust for the tz
ull += ltzHour * (__int64)-10000000;
// Save the result into the FILETIME structure.
m_ftEarliest.dwLowDateTime = (DWORD) (ull & 0xFFFFFFFF);
m_ftEarliest.dwHighDateTime = (DWORD) (ull >> 32);
http://msdn.microsoft.com/en-us/library/t6z7bya3(VS.80).aspx
Tom
"Michael Tissington" <nos...@nospam.com> wrote in message
news:%238AF$yYgJH...@TK2MSFTNGP05.phx.gbl...