1

I need to send DateTime object as string

So that I'll be able to parse this string back to DateTime and not lose data.

i.e. restore the original object.

Which format should I use?

SeReGa
  • 1,219
  • 2
  • 11
  • 32
  • 2
    Why can't you "send" it as a datetime object? The answer depends on how you are sending it. – DavidG Feb 11 '19 at 15:03
  • yyyy/MM/dd HH:mm:ss (with timezone or UTC if need be). – Cetin Basoz Feb 11 '19 at 15:04
  • @DavidG, because the system works in this way... – SeReGa Feb 11 '19 at 15:19
  • 3
    @CetinBasoz that's a localized format. – Panagiotis Kanavos Feb 11 '19 at 15:19
  • Yes localized and safe for that reason. As I added, if you want UTC just use UTC. – Cetin Basoz Feb 11 '19 at 15:20
  • 4
    @CetinBasoz and *definitely unsafe* for that reason. It will *fail* in any locale that doesn't use that specific format. Nothing says that the four letters at the front are a year, or that the middle ones are months. The ISO8601 format is unambiguous though – Panagiotis Kanavos Feb 11 '19 at 15:21
  • Nothing says? Check ISO 8601 as an example. – Cetin Basoz Feb 11 '19 at 15:22
  • 3
    @Cetin that's NOT ISO8601. ISO8601 uses dashes. – Panagiotis Kanavos Feb 11 '19 at 15:23
  • If you say so :) – Cetin Basoz Feb 11 '19 at 15:23
  • 3
    @CetinBasoz There is no "if you say so", it's simply a fact. See [here](https://stackoverflow.com/questions/114983/given-a-datetime-object-how-do-i-get-an-iso-8601-date-in-string-format) for example. – DavidG Feb 11 '19 at 15:25
  • 2
    @CetinBasoz check the actual [ISO standard](https://www.iso.org/iso-8601-date-and-time-format.html). You can check the [ISO 8601 Wikipedia page](https://en.wikipedia.org/wiki/ISO_8601) to avoid downloading the actual standard text – Panagiotis Kanavos Feb 11 '19 at 15:25
  • ISO8601 says it is yyyy-MM-dd, not as you claimed it could be yyyy-dd-MM – Cetin Basoz Feb 11 '19 at 15:27
  • @PanagiotisKanavos, if you don't want to fail with some locale, say on SQL Server, then you shouldn't even use dashes or / or . - any separator for date part. That fails on sone language settings and versions (thus the one you found safe fail). – Cetin Basoz Feb 11 '19 at 15:29
  • 3
    @CetinBasoz SQL Server specifically handles ISO8601 format, which uses dashes. It's unclear why you are digging in so much on this. – DavidG Feb 11 '19 at 15:33
  • 2
    @CetinBasoz - noone claimed that *ISO8601* says it could be `yyyy-dd-MM`. What *was* claimed is that with your proposed format `"yyyy/MM/dd"` you could for example get something like `"2019/02/11"` and there would be no way to definitely know that this would really be `"2019-02-11"` or `"2019-11-02"`. *Only* if both sides agree, what format should be used. -- *With* ISO8601 there is *no* ambiguity, because `"yyyy-dd-MM"` is **not** ISO8601. – Corak Feb 11 '19 at 15:37
  • @Corak, where would it say ISO8601? You are agreeing upon it, no? PK implied it could be yyyy/dd/MM, wouldn't it be always yyyy/MM/dd too upon agreement. My fault was not saying ISO8601 but just yyyy/MM/dd HH:mm:ss? – Cetin Basoz Feb 11 '19 at 16:42
  • 1
    @DavidG, in some older versions of MS SQL, with some language combinations, it is well demonstrated that MS SQL Server fail to interpret yyyy-MM-dd ... aka ISO8601 format. It can only interpret it when you remove the separators. You might find the demo code on MSDN forums if you search. – Cetin Basoz Feb 11 '19 at 16:45
  • 2
    @CetinBasoz - using dashes implicitly broadcasts "this is ISO8601". Using slashes *doesn't*. -- Also, `"/"` in the format string will be replaced by the `DateSeparator` of whatever `DateTimeFormat` is being used. That *might* also be `"/"`, but doesn't *have* to be. Try `DateTime.Now.ToString("yyyy/MM/dd", CultureInfo.GetCultureInfo("de-DE"))` for example. Dashes in the format string will remain untouched. – Corak Feb 12 '19 at 07:26
  • @Corak, so you are saying 01-01-2019 is ISO8601. Good:) The thing doesn't have anything to do with cultures. Try parsing with /, . or -. All parses correctly. – Cetin Basoz Feb 12 '19 at 13:00
  • 2
    @CetinBasoz - No I don't. Yes it does. Have fun. – Corak Feb 12 '19 at 13:22

1 Answers1

8

Use the round-trip format "O":

string s = dateTime.ToString("O");
DateTime d =
    DateTime.ParseExact(s, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind);
Cory Nelson
  • 29,236
  • 5
  • 72
  • 110
  • Seems Good, I just did not understand the difference between "o" and "O". – SeReGa Feb 11 '19 at 15:10
  • 1
    @SeReGa there is no difference between the two. – Cory Nelson Feb 11 '19 at 15:12
  • While you are right to suggest the round-trip format, my comment on the question still stands. Also, you need to use the same culture when converting to string as well as parsing back to a date. – DavidG Feb 11 '19 at 15:13
  • 2
    @DavidG "O" is always invariant, no need to specify a culture. – Cory Nelson Feb 11 '19 at 15:14
  • D'oh, yes, of course it does. But I would still strive to not convert it to anything if possible. – DavidG Feb 11 '19 at 15:17
  • 1
    Keep in mind that while the round-trip format does what it's supposed to, `DateTimeKind.Local` could mean different things between the sender and the receiver. If so, the resulting timestamp will be the same point in time (the UTC equivalent), but will be adjusted to the receiver's local time zone. If you don't want that behavior, you need to use a `DateTimeOffset` instead of a `DateTime`. – Matt Johnson-Pint Feb 11 '19 at 17:35