0

I am consuming a Web Service which will return datetime fields in response object.

My reference.cs file has,

private System.DateTime timestampField;

public System.DateTime Timestamp {
    get {
        return this.timestampField;
    }
    set {
        this.timestampField = value;
    }
}

In SOAP UI when I called the service I see it's returning as 2014-06-09T21:24:56+00:00 , 2014-06-17T05:42:00-04:00

I have different Offsets for Different values..

But from my .NET App when I am calling it's converting to some other value as 6/9/2014 5:24:56 PM but it should be whose actual value is 6/9/2014 9:24 pm.

How can I fix this?

msbyuva
  • 3,467
  • 13
  • 63
  • 87
  • 1
    How are you seeing the value? My guess is that it's just converting it from UTC to your local time. Can you use `DateTimeOffset` instead?> – Jon Skeet Jun 17 '14 at 17:32
  • @JonSkeet I used SOAP UI to view the response.. – msbyuva Jun 17 '14 at 17:49
  • The +00:00 at the end shows you it's returning a time in UTC. The "converted" value you see is in your local time. – Kevin Jun 17 '14 at 17:52
  • What do you mean by "SOAP UI" exactly? And I was more asking about the "from my .NET App" part... are you just calling `DateTime.ToString()` for example? – Jon Skeet Jun 17 '14 at 18:07
  • @JonSkeet SOAP UI is webservice testing tool -- we can see response from the service -- http://en.wikipedia.org/wiki/SoapUI and in .NET App it's just DateTiem field -- form object I am just looking in to the value of class.Timestamp – msbyuva Jun 17 '14 at 18:11
  • @Kevin I applied UTC -- ToUniversalTime() it's increasing the time by 4 hours for exmaple if time is 2014-06-09T16:24:56+00:00 , its getting converted to 6/14/2014 08:24:56 PM – msbyuva Jun 17 '14 at 18:19
  • Are you using "Add Service Reference", or "Add Web Reference"? Also, which version of .NET are you using? – John Saunders Jun 17 '14 at 18:40
  • @msbyuva - It shouldn't be doing that. Can you check the `Kind` of the value before you call `ToUniversalTime`? It should be `Local`. – Matt Johnson-Pint Jun 17 '14 at 18:40
  • And can you use `DateTimeOffset` instead of `DateTime`? It's likely to keep this a bit clearer. – Jon Skeet Jun 17 '14 at 18:44
  • @JohnSaunders I am using Add Web Reference and .NET version I am using is .NET 4.0 – msbyuva Jun 17 '14 at 18:51
  • @MattJohnson I checked Kind and it's Local – msbyuva Jun 17 '14 at 18:52
  • @JonSkeet changed to use DateTimeOffset it's returning 1/1/0001 12:00:00 AM +00:00 – msbyuva Jun 17 '14 at 18:54
  • That's odd - that suggests it's not parsing it at all. Can you update your question with a full example of: 1) the value from the web service; 2) the value of the `DateTime` including `Kind`; 3) the value of the result of calling `ToUniversalTime()`? We've got different examples which are getting a bit muddled here... – Jon Skeet Jun 17 '14 at 18:58
  • @JonSkeet -- 1. value coming from Web Service -- 2014-06-17T05:42:00-04:00 2. Value of DateTime including Kind -- Local 3. Value of the result calling ToUniversalTime() -- 6/17/2014 9:42:00 AM – msbyuva Jun 17 '14 at 19:03
  • @msbyuva: That's now a very different example from the original one, which had an offset of +00:00. Are you really seeing different offsets for different values? That's entirely feasible, but surprising.You haven't included the value of the local one in step 2... and please update the *question* with all of this information. – Jon Skeet Jun 17 '14 at 19:07
  • @JonSkeet YEAH i HAVE Different OFFSETs for Different VALUES -- value of DateTimeKind is -- local -- 06/17/2014 5:42:00 AM – msbyuva Jun 17 '14 at 19:16
  • Not sure why you're shouting now, or why you *still* haven't edited this into the question - but it looks like `ToUniversalTime` is doing the right thing in this case - but in your earlier comment it sounded like it was broken. Hmm. – Jon Skeet Jun 17 '14 at 19:19
  • @JonSkeet I have different offsets for different values -- if it's -ve DateTime.SpecifyKind(timevalue, DateTimeKind.Local)), is getting correct value but if its +ve offset I need to convert to UniversalTime I am wondering that can I have something comman which converts both offsets ? – msbyuva Jun 17 '14 at 19:21
  • I'm afraid it sounds like there's altogether too much bizarre stuff going on for me to help like this - Stack Overflow doesn't work well as a remote debugging tool, where we have to keep going back and forth to get more information. (This is the first time you've mentioned SpecifyKind, and you haven't given any examples with positive offsets...) – Jon Skeet Jun 17 '14 at 19:23
  • 2014-06-09T21:24:56+00:00 – msbyuva Jun 17 '14 at 19:25
  • @msbyuva: in general, you should use "Add Service Reference". "Add Web Reference" is part of the legacy ASMX technology, and should not be used for new development. – John Saunders Jun 17 '14 at 22:23

2 Answers2

4

When you consume a SOAP web service that uses xsd:dateTime, Visual Studio will always create the client proxy class using a DateTime.

  • If there is no offset in the data, the values will come across with DateTimeKind.Unspecified.

  • If instead of an offset, the Z specifier is sent, then the values will come through with DateTimeKind.Utc.

  • If there is any offset at all, then the values come through with DateTimeKind.Local. Even when the offset is zero. Whatever the offset is, it is applied, and then the value is converted to local time. Essentially, it calls .ToLocalTime() internally.

This kind of stinks, but the easiest way to deal with it is to convert back to UTC using .ToUniversalTime(), or convert to another time zone using the TimeZoneInfo object.

Thanks to the hidden "4th kind", you can safely convert from local back to UTC without ambiguity. (The offset from the original value will disambiguate.)

As far as I know, there is no way to get it to create a DateTimeOffset instead. That would be ideal. However, if you really want to dive deep, you may be able to get it to ignore the offset completely - though that's not necessarily the best idea.

Also, it's worth mentioning that if you were to try to create your own service and expose a DateTimeOffset type directly - you'd run into problems. There isn't a mapping from DateTimeOffset back to xsd:dateTime or any of the other XML Schema data types used by SOAP. Instead, you get a custom complex type in the schema, and the data doesn't get passed along at all. On the client, instead of receiving a System.DateTimeOffset, you get a YourServiceReference.DateTimeOffset object that doesn't do anything at all. It's unfortunate, because it should be great advice to use DateTimeOffset in a public-facing API, but it simply doesn't work. At least not for SOAP/XML. Things are much better in the REST/JSON world.

Community
  • 1
  • 1
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
0

This is what I did, not sure if it's the efficient way..

I had different offset values for different time values and I don't know the timezone from the time field value... what I did is

I converted the time field value to string and got the offset using sub string and applied that to the UTC of time field value

     TimeSpan offSetSpan = new TimeSpan();
          string dt = TimestampValue;
          string offset = TimestampValue.Substring(trackevent.Timestamp.Length - 6,6);

          if (offset != "+00:00" && offset != "-00:00")
                                {
                                    offSetSpan = TimeSpan.Parse(offset.Trim());
                                }
Console.WriteLine("Offset Timestamp: {0}", Convert.ToDateTime(TimestampValue).ToUniversalTime() + offSetSpan);
msbyuva
  • 3,467
  • 13
  • 63
  • 87
  • 1
    If you're doing that client-side, then the offset you get out of the substring is just your own *local* offset, which isn't necessarily the same offset in the original data. If you want to get at that, you'd have to go down the complex route of creating a custom WCF formatter as shown in the question I linked to in my answer. – Matt Johnson-Pint Jun 17 '14 at 21:41