0

I am having an issue converting this date format into another format. I was hoping that somebody on here would be able to help me out.

Here is my code:

string fromFormat = "ddd, dd MM yyyy HH:mm:ss zzz"; 
string toFormat = "yyyy-MM-dd";

DateTime newDate = DateTime.ParseExact("Mon, 25 03 2013 00:00:00 GMT", fromFormat, null);

Console.WriteLine(newDate.ToString(toFormat));

-------EDIT--------

I was able to get rid of my errors by changing the day from 22 to 25. My new issue is trying to get the timezone to convert from GMT to EST. Would anyone have any ideas?

-------EDIT #2-------

Here is my current code as it stands. I am still having issues with a timezone conversion.

var date = "Mon, 25 03 2013 00:00:00 GMT";

// Cuts off "GMT" portion of string
string newdate = date.Substring(0, 24);

// Switches the output of date
string fromFormat = "ddd, dd MM yyyy HH:mm:ss";
string toFormat = "yyyy-MM-dd";

DateTime newDate = DateTime.ParseExact(newdate, fromFormat, null);
string finaldate = newDate.ToString(toFormat);

// Output final date
Console.WriteLine(finaldate);

-------EDIT #3-------

The code:

var input = "Mon, 25 03 2013 00:00:00 GMT";
var inner = input.Substring(0, 24);
var format = "ddd, dd MM yyyy HH:mm:ss";
var zoneId = "Eastern Standard Time";

var parsed = DateTime.ParseExact(inner, format, CultureInfo.InvariantCulture);

var utcDateTime = DateTime.SpecifyKind(parsed, DateTimeKind.Utc);
var eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcDateTime, zoneId);


Console.WriteLine(eastern);

The error:

Unhandled Exception: System.TimeZoneNotFoundException: Exception of type
   'System.TimeZoneNotFoundException' was thrown.
at System.TimeZoneInfo.FindSystemTimeZoneByFileName (System.String id, System.String
   filepath) [0x00000] in :0 
at System.TimeZoneInfo.FindSystemTimeZoneById (System.String id) [0x00000] in :0 
at System.TimeZoneInfo.ConvertTimeBySystemTimeZoneId (DateTime dateTime, System.String 
   destinationTimeZoneId) [0x00000] in :0 
at Program.Main () [0x00000] in :0 

Any help would be much appreciated! Thanks!

-------FINAL EDIT-------

This is what ended up changing the timezone and converting to the format that I needed. Special thanks to @MattJohnson for all of his help!

// Cuts off 'GMT' portion of string
var newdate = date.Substring(0, 24);

var fromFormat = "ddd, dd MM yyyy HH:mm:ss";
var toFormat = "yyyy-MM-dd";
var zoneId = "Eastern Standard Time";


var parsed = DateTime.ParseExact(newdate, fromFormat, CultureInfo.InvariantCulture);

// Specifies UTC time and converts it to EST timezone
var utcDateTime = DateTime.SpecifyKind(parsed, DateTimeKind.Utc);
var eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcDateTime, zoneId);

// Converts date to final format needed
var finaldate = eastern.ToString(toFormat);
scapegoat17
  • 5,509
  • 14
  • 55
  • 90

7 Answers7

5
string fromFormat = "ddd, dd MM yyyy HH:mm:ss zzz"; 

The error is your zzz, it is expecting the numerical representation of the timezone, not the abbreviation of the timezone.

So a acceptable version would be

DateTime newDate = DateTime.ParseExact("Mon, 22 03 2013 00:00:00 +0:00", fromFormat, null);

but that would throw a different FormatExecption with the message "String was not recognized as a valid DateTime because the day of week was incorrect." If you make the Monday to Friday correction the parse works

DateTime newDate = DateTime.ParseExact("Fri, 22 03 2013 00:00:00 +0:00", fromFormat, null);

I don't think there is a format specifier that can take in the textual abbreviation version of the timezone.

Community
  • 1
  • 1
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
  • There isn't one. He'd have to roll his own for that. – Curtis Rutland Jul 09 '13 at 19:21
  • I even if i take out the `zzz` and `GMT` portion of the code, it still throws the same error. The error will stop when i remove both, the `ddd` and the `zzz` portion. – scapegoat17 Jul 09 '13 at 19:23
  • You do not get the "Same" error, refresh the page I added more info, You still get a `FormatExecption` but it has a different message. – Scott Chamberlain Jul 09 '13 at 19:25
  • I think i may be misunderstanding what you are saying, but i am unable to control whether it says `Mon` or `Fri`. It could be `Mon`, `Tue`, `Wed`, etc... – scapegoat17 Jul 09 '13 at 19:33
  • 1
    The exact parsing of March 22 2013 was a Friday - this is why the FormatException is being thrown. If you are getting the date from an external source, the data is incorrect. – ClosedEyesSeeing Jul 09 '13 at 19:37
  • 1
    You are misunderstanding, because the date you tested with is incorrect. 2013-03-22 is not a Monday, it's a Friday. – Curtis Rutland Jul 09 '13 at 19:38
  • 1
    If the `Mon`, `Tue`, `Wed` is not reliable you must remove it from the string before you attempt to parse it and remove the ddd portion. – Scott Chamberlain Jul 09 '13 at 19:46
  • That was the error. I am just going to work on converting everything into EST and trimming the timezone portion off. Does anyone have any good ideas on how to do the latter? @ScottChamberlain – scapegoat17 Jul 09 '13 at 19:54
  • @jpriff - That's not necessarily the best idea. But you would do that with the `TimeZoneInfo` class. You might want to ask with the particulars in a new question. Or look at the many similar questions that have already been answered. – Matt Johnson-Pint Jul 09 '13 at 19:57
  • @MattJohnson why do you believe this is not the best idea? – scapegoat17 Jul 09 '13 at 21:24
  • @jpriff - Because of daylight saving time and time zone issues. `DateTime` doesn't track these things. Of course it depends on what you actually want to do with the data. That's why I recommend you ask in a new question (but just on the time zone portion!) :-) – Matt Johnson-Pint Jul 09 '13 at 21:28
  • @MattJohnson - haha, I understand. That should not really effect what I am using it for. I have a bunch of GMT that I need to convert into EST and then format it into yyyy-MM-dd. I don't really see how to get that timezone conversion to work though... – scapegoat17 Jul 09 '13 at 21:32
2

As others pointed out, the input value you have is self-inconsistent. It refers to a March 22 2013 as a Monday when it is actually a Friday. So you should go back to your source data and figure out why that happens. I'm sure you have heard the saying, "Garbage In, Garbage Out".

If you are sure you want to ignore the day of week, and you are certain that the time zone will always be GMT, then you can do this:

var input = "Mon, 22 03 2013 00:00:00 GMT";
var inner = input.Substring(5, 19);
var format = "dd MM yyyy HH:mm:ss";
var parsed = DateTime.ParseExact(inner, format, CultureInfo.InvariantCulture);
var utcDateTime = DateTime.SpecifyKind(parsed, DateTimeKind.Utc);

Note that I explicitly set the kind to UTC, because you are bringing in GMT values. GMT and UTC are identical for all practical purposes.

If it's possible that other time zone values will be passed, then please provide a sampling of different possible inputs and perhaps we can find a way to accommodate that.

As an aside - this string looks very similar to RFC822/RFC1123 formatted dates, except you are passing the month as a number instead of one of the three-letter abbreviations. Did you do this intentionally? If so, you have broken the spec for this format. If your intention was to remove potentially localizable strings from the data, then please use a format that is already designed for that, such as ISO8601/RFC3339.

On Time Zones

You said you want to convert to EST, You probably mean "US Eastern Time", which alternates between EST and EDT for daylight saving time. Despite this, the Windows Time Zone database uses the id of "Eastern Standard Time" to refer to both values - so try not to get confused on that point.

Once you have the date as a DateTime of Utc kind, as I showed above, you can convert that to Eastern Time with the following:

var zoneId = "Eastern Standard Time"; // don't get confused here! :)
var eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcDateTime, zoneId);

Just be careful what you do with this value. If you are displaying it to an user, then you are ok. Just do this:

var s = eastern.ToString("g"); // or whatever format you want.

But if you do math with this, or store it as an recorded event time, you are potentially introducing errors into your results. This is due to daylight saving time transitions. One way to avoid this is to use a DateTimeOffset type instead:

var utcDateTimeOffset = new DateTimeOffset(utcDateTime, TimeSpan.Zero);
var eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcDateTimeOffset, zoneId);

Now when you work with these values, any ambiguities are captured by the offset.

If this seems very confusing to you, don't worry - you're not alone. You might want to try using Noda Time instead. It will prevent you from shooting yourself in the foot.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Wow, what a write up! I must have missed it with all of the other posts that were coming in yesterday :) I have a few answers and questions for you though! Firstly, it will always be `GMT` time and it will only need to be converted into `EST` time. As you have showed above, do I need to convert to `UTC` to get it to go to `EST` time? Or can I just leave it as is? Also, the code that you have shown above, will that account for daylight savings time? I know you told me not to get confused, but I did :) Sorry! – scapegoat17 Jul 10 '13 at 13:29
  • GMT *is* UTC. You need to tell it you have UTC, or the `DateTime` conversion to ET will be incorrect. You could skip that for the `DateTimeOffset` conversion, but its more correct to leave it in place. Yes, the code (as is) will account for DST. That's part of what `TimeZoneInfo` conversions do. – Matt Johnson-Pint Jul 10 '13 at 15:44
  • I have am still having issues with trying to incorporate your code. It seems that I am getting string errors. The new edit that I made above is what I used to get it to work without the timezone conversion. I tried adding your code lines: `var zoneId = "Eastern Standard Time";` `var eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcDateTime, zoneId);` `var utcDateTimeOffset = new DateTimeOffset(utcDateTime, TimeSpan.Zero);` `var eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(utcDateTimeOffset, zoneId);` I did changed the variable names but still no dice... – scapegoat17 Jul 10 '13 at 17:20
  • There are two different options there, pick one. Don't use both. But if you are getting string errors, then it has more to do with the upper section. You'll have to be more specific about what you tried and what isn't working. – Matt Johnson-Pint Jul 10 '13 at 20:04
  • Looking at your edit, I see you are passing `null` where you should pass `CultureInfo.InvariantCulture`. `null` means to use the current culture, which may or may not work depending on what culture you are actually using. Also, make sure to specify the kind as Utc before trying to convert to EST. I show that above in `DateTime.SpecifyKind` – Matt Johnson-Pint Jul 10 '13 at 20:09
  • The reason why I changed it to `null` was because `Culture.Info.InvariantCulture` was giving me errors saying `The name CultureInfo does not exist in the current context`. Is that because i need to reference something? – scapegoat17 Jul 11 '13 at 14:51
  • `using System.Globalization` – Matt Johnson-Pint Jul 11 '13 at 15:13
  • I am trying to replicate your code so i can have a better understanding. I paste what I have up top as to how I understood your instructions. Do you have any idea as to what the issue may be here? Thanks! – scapegoat17 Jul 11 '13 at 20:01
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/33307/discussion-between-matt-johnson-and-jpriff) – Matt Johnson-Pint Jul 11 '13 at 20:45
1

To see what's wrong, print a DateTime using your fromString:

DateTime dt = new DateTime(2013, 3, 22);
string s = dt.ToString(fromFormat);

you'll see that the output is:

Fri, 22 03 2013 00:00:00 -04:00

so that is the format it would be expecting.

You might be able to get some help on the abbreviations from this article.

Community
  • 1
  • 1
Michael Bray
  • 14,998
  • 7
  • 42
  • 68
0

22 03 2013 00:00:00 GMT is not Monday it's Friday

try

            string fromFormat = "ddd, dd MM yyyy HH:mm:ss zzz";
            string toFormat = "yyyy-MM-dd";

            Console.WriteLine(DateTime.ParseExact("Fri, 22 03 2013 00:00:00 +00:00", fromFormat,
                             CultureInfo.InvariantCulture).ToString(toFormat));
Alyafey
  • 1,455
  • 3
  • 15
  • 23
0

There are two issues:

1) The day selected was a Friday not a Monday

2) The 'zzz' wants a plus or minus 0:00

So, to get it to work would be:

string fromFormat = "ddd, dd MM yyyy HH:mm:ss zzz";
string toFormat = "yyyy-MM-dd";

DateTime newDate = DateTime.ParseExact("Fri, 22 03 2013 00:00:00 +0:00", fromFormat, null);

Console.WriteLine(newDate.ToString(toFormat));
0

There's no simple, built-in way to convert from a Time Zone abbreviation to an offset or proper name. This is discussed in this topic here:

Timezone Abbreviations

You'll either need to create a table of the abbreviations you want to use, mapped to an offset or proper name, or you'll need to change the format of your incoming date/time string to use offsets.

Community
  • 1
  • 1
Curtis Rutland
  • 776
  • 4
  • 12
0
string fromFormat = "ddd, dd MM yyyy HH:mm:ss zzz"; 
string toFormat = "yyyy-MM-dd";

DateTime newDate = DateTime.ParseExact("Mon, 22 03 2013 00:00:00 +00:00", fromFormat, null);

Console.WriteLine(newDate.ToString(toFormat));