How to change DateTime UTC in WCF service - c#

I have a WCF service returning opening and closing times.
The problem is that the time is always represented with UTC+2.
Here's an example of my WCF code:
[XmlElementAttribute(Form = Schema.XmlSchemaForm.Unqualified, DataType = "time", Order = 1)]
public System.DateTime OpeningTime
{
get
{
string timeString = "10:00:00";
return XmlConvert.ToDateTime(timeString, XmlDateTimeSerializationMode.RoundtripKind);
}
}
The result in the response is:
<OpeningTime>10:00:00.0000000+02:00</ClosingTime>
But I need it with UTC 0 like
<ClosingTime>10:00:00.0000000+00:00</ClosingTime>
I have no clue how I can specify the timezone. I also tried using ToLocalTime() but it is always UTC+2.
I need the time as DateTime so converting the DateTime to string is no option.

Related

How to parse a timespan in order to add it to a datetime?

I've got a string in the following format: 05/06/2019|1330|60
The output I'm looking for is: 05/06/2019T14:30:00
I'm attempting to parse out the TimeSpan portion right now:
public static string getProcedureEndingDateTime (string input) {
//05/06/2019|1330|60
string myDate = input.Split ( '|' ) [0];
DateTime myDateTime = DateTime.Parse (myDate);
string myTime = input.Split('|')[1];
string hours = myTime.Substring(0,2);
string minutes = myTime.Substring(2,2);
TimeSpan myTimeSpan = TimeSpan.Parse($"{hours}:{minutes}");
myDateTime.Add(myTimeSpan);
return myDateTime.ToString();
}
But right now, getting the following output:
To get the above output I'm calling my function like so:
Console.WriteLine (getProcedureEndingDateTime("05/06/2019|1330|60"));
How do I parse the string "1330" into a TimeSpan?
No need to us a Timespan here, just call ParseExact instead with a proper format to do it in one line.
var myDateTime = DateTime.ParseExact("05/06/2019|1330|60", "dd/MM/yyyy|HHmm|60", CultureInfo.InvariantCulture);
Console.WriteLine(myDateTime.ToString());
//this gives 2019-06-05 1:30:00 PM, format depends on your PC's locale
I don't know what the 60 part is, you can adjust the format or substring it out beforehand.
The problem is because Add() returns a new DateTime instance, which means you're currently discarding it. Store it, and return that from your function instead, like so:
var adjusted = myDateTime.Add(myTimeSpan);
return adjusted.ToString();
Try using the numeric values as exactly that, numbers.
Also, the other issue with your code is the DateTime.Add() method doesn't add to that DateTime variable. Instead it returns a new variable, which you are ignoring.
Try this:
public static string getProcedureEndingDateTime (string input) {
string[] parts = input.Split('|');
string myDate = parts[0];
DateTime myDateTime = DateTime.Parse (myDate);
string myTime = parts[1];
if (!int.TryParse(myTime.Substring(0,2), out int hours))
hours = 0;
if (!int.TryParse(myTime.Substring(2,2), out int minutes))
minutes = 0;
TimeSpan myTimeSpan = new TimeSpan(hours, minutes, 0);
myDateTime += myTimeSpan;
return myDateTime.ToString();
}
Assuming the date shown is May 6th (and not June 5th), and also assuming the 60 represents a time zone offset expressed in minutes west of GMT, and also assuming you want the corresponding UTC value, then:
public static string getProcedureEndingDateTime (string input) {
// example input: "05/06/2019|1330|60"
// separate the offset from the rest of the string
string dateTimeString = input.Substring(0, 15);
string offsetString = input.Substring(16);
// parse the DateTime as given, and parse the offset separately, inverting the sign
DateTime dt = DateTime.ParseExact(dateTimeString, "MM/dd/yyyy|HHmm", CultureInfo.InvariantCulture);
TimeSpan offset = TimeSpan.FromMinutes(-int.Parse(offsetString));
// create a DateTimeOffset from these two components
DateTimeOffset dto = new DateTimeOffset(dt, offset);
// Convert to UTC and return a string in the desired format
DateTime utcDateTime = dto.UtcDateTime;
return utcDateTime.ToString("MM/dd/yyyy'T'HH:mm:ss", CultureInfo.InvariantCulture);
}
A few additional points:
Not only is the input format strange, but so is your desired output format. It is strange to see a T separating the date and time and also see the date in the 05/06/2019 format. T almost always means to use ISO 8601, which requires year-month-day ordering and hyphen separators. I'd suggest either dropping the T if you want a locale-specific format, or keep the T and use the standard format. Don't do both.
In ISO 8601, it's also a good idea to append a Z to UTC-based values. For DateTime values, the K specifier should be used for that. In other words, you probably want the last line above to be:
return utcDateTime.ToString("yyyy-MM-dd'T'HH:mm:ssK", CultureInfo.InvariantCulture);
// outputs: "2019-05-06T14:30:00Z"
You might want to not format a string here, but instead return the DateTime or DateTimeOffset value. It's usually better to create a string only at the time of display.
Don't forget that the DateTime struct is immutable. In your question you were ignoring the return value of the Add method.

Date read from Database in wrong format?

I'm using DateTime in my C# winforms tool, and I'm storing dates into an SQL database using this line:
iDisc.acquirementDate.ToString("yyyy-MM-dd")
The SQL database field is of DATE type, and when this date is stored, its stored correctly, such as this: 2013-03-14
When I want to the value, I use this line:
DateTime acquirementDate = DateTime.ParseExact(iDiscRow[TableNames.Discs.acquirementDate].ToString(), "yyyy-MM-dd", CultureInfo.InvariantCulture);
However, a FormatException occurs at the above line, because the string being parsed is not a valid DateTime complaint string.
The value this is being parsed is the this: 3/14/2013 12:00:00 AM
What I don't understand is, why is the value read as 3/14/2013 12:00:00 AM, when in the database its stored as 2013-03-14 ?
I'm using SqlDataReader to retrieve the data from database. Can post that code here, but I don't think its needed as its very basic.
It seems that your iDiscRow[TableNames.Discs.acquirementDate] is DateTime already. In that case you just have to cast it.
DateTime acquirementDate = (DateTime)iDiscRow[TableNames.Discs.acquirementDate];
And reason why you're getting 3/14/2013 12:00:00 AM is that DateTime.ToString() uses current thread culture to trasnform DateTime to string. Since it's WinForm app, I guess this is your Windows system format for DateTime.
The row is retrieved as an object. The ToString() method is formatting it. You need to pass the format you want to use to the ToString() method.
This answer is only relevent if it's possible for the database value to be null. That is frequently my own situation, so I wrote this function in a helper class in a class library.
public DateTime? SetDateTimeValue(DataTable dataTableIn
, int rowNumber, string fieldName)
{
DateTime? returnValue = new DateTime?();
DateTime tempValue = new DateTime();
try
{
string fieldValueAsString = dataTableIn.Rows[rowNumber][fieldName].ToString();
result = DateTime.TryParse(fieldValueAsString, out tempValue);
if (result)
returnValue = tempValue;
}
catch
{
returnValue = null;
}
return returnValue;
}
Here is a sample call
DataTable data = dataAccess.GetEmergencyVisitDataFromClinicalApplicationSupport(VisitID);
if (data.Rows.Count == 1)
{
ValueSetter setterOfValues = new ValueSetter();
skip a bunch of lines.
AdmitDecisionDateTime =
setterOfValues.SetDateTimeValue(data, 0, "admit_decision_datetime");

Get Date from DateTime without ToShortDateString

I am searching for this for about 2 hours and I don't have any ideas anymore.
The problem is I have a DateTime object and I need only the date part from it.
I tried
data.Date
create a new DateTime object like this
var x = new DateTime(data.Year,data.Months,data.Day)
I tried like this
DateTime.Parse(data.ToString("yyyy-MM-dd"))
NOTE: After getting the date part only, data needs to remain DateTime ( not string ), so I can not use ToShortDateString()
If you want some object, witch always return date in 2012-10-10 format from .ToString(), you can use this struct
struct Date
{
private DateTime dateTime;
public Date(DateTime dateTime)
{
this.dateTime = dateTime.Date;
}
public override string ToString()
{
return dateTime.ToString("yyyy-MM-dd");
}
}

Parsing a JSON date info into a C# DateTime

I have a a WCF service that returns a CLR object. This object is defined as follows:
[DataContract]
public class Person
{
[DataMember]
public string FullName
{
get { return fullName; }
set { id = fullName; }
}
private string fullName = string.Empty;
[DataMember]
public DateTime BirthDate
{
get { return birthDate; }
set { birthDate = value; }
}
}
Instances of this object are being created and returned from my WCF service. This service looks like the following:
[OperationContract]
[WebGet(UriTemplate = "/GetPersonByID/{id}", ResponseFormat = WebMessageFormat.Json)]
public Person GetPersonByID(string id)
{
Person person = FindPersonByID(id);
return person;
}
When I get the response back in my application, I can successfully extract the FullName value. However, I haven't successfully been able to convert the BirthDate to a C# DateTime object in my client application. When converted to a string, the BirthDate looks something like this:
\/Date(1297367252340-0500)\/
How do I get that into a C# DateTime instance?
Thanks!
Here are two options:
You can use the Deserialize method from System.Web.Script.Serialization.JavaScriptSerializer (in System.Web.Extensions.dll).
or you could use the ReadObject method from System.Runtime.Serialization.Json.DataContractJsonSerializer (in System.Runtime.Serialization.dll or in .NET 3.5 in System.ServiceModel.Web.dll).
Make sure that your date is wrapped in quotes like:
string dateString = #"""\/Date(1297367252340-0500)\/""";
The reason the date is in this weird format is that DateTime is a primitive in WCF. Unfortunately, there is no universally standardized format for serializing dates and times in JSON -- various frameworks use various string formats.
The dilemma is that WCF needs to natively understand that a particular string over the wire is indeed a DateTime, not just another plain vanilla JSON string. Hence the strange format. As soon as DataContractJsonSerializer encounters a date starting with \/Date, it starts trying to parse it as a date.
Now, to answer your question, when you are sending a DateTime over the wire, it depends on if you're using a web browser client, a Silverlight client, or a WCF client.
A WCF client or a Silverlight 2+ client should NOT have problems with this -- they should auto-use the DataContractJsoNSerializer, and if they're not using it, you can plug in DCJS manually.
If you are using a web client, you can include the .js file that ships with ASP. NET AJAX (I believe it is called MicrosoftAspNetAjax.js, or MicrosoftAjax.cs, though the name may have changed). Its deserialize function will auto-parse these dates as well.
Hope that helps!
Well, lately I had to work on an Android Mobile (Xamarin Studio) app project where I was unable to use Newtonsoft Json (Json.NET) due to errors thrown during deployment to this specific device version (Android API 16 Version 4.2.1).
Luckly I found an alternative library for json (System.Json). However this library does not have a way of casting JSON date to C# DateTime implicitly.
I have created the following two functions for nullable date and date conversions from a string json date(i.e /Date(1389435240000+0000)/)
The code can be improved but it does the job for now
public static DateTime? ConvertToNallableDate(string date)
{
DateTime? val = null;
/* /Date(1389435240000+0000)/*/
try{
if(!string.IsNullOrEmpty(date))
{
date = date.Replace ("/Date(", string.Empty).Replace (")/", string.Empty);
int pIndex = date.IndexOf ("+");
if(pIndex < 0) pIndex = date.IndexOf("-");
long millisec = 0;
date = date.Remove (pIndex);
long.TryParse (date, out millisec);
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("en-GB");
DateTime newDate = DateTime.Parse ("1970,1,1", ci);
newDate = newDate.AddMilliseconds(millisec);
val = newDate == null ? (DateTime?)null : newDate;
}
}catch {
val = null;
}
return val;
}
public static DateTime ConvertToDate(string date)
{
DateTime val = new DateTime();
/*/Date(1389435240000+0000)/*/
try{
if(!string.IsNullOrEmpty(date))
{
date = date.Replace ("/Date(", string.Empty).Replace (")/", string.Empty);
int pIndex = date.IndexOf ("+");
if(pIndex < 0) pIndex = date.IndexOf("-");
long millisec = 0;
date = date.Remove (pIndex);
long.TryParse (date, out millisec);
System.Globalization.CultureInfo ci = new System.Globalization.CultureInfo("en-GB");
DateTime newDate = DateTime.Parse ("1970,1,1", ci);
val = newDate.AddMilliseconds(millisec);
}
}catch {
val = new DateTime();
}
return val;
}
This solved my problem
using System.Web.Script.Serialization;
//code
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
DateTime ddate = json_serializer.Deserialize<DateTime>(#"""\/Date(1326038400000)\/""").ToLocalTime();

Force XmlSerializer to serialize DateTime as 'YYYY-MM-DD hh:mm:ss'

I have a XSD schema for some RESTful service. When used in conjunction with xsd.exe tool to generate C# code, XSD's xs:date generates the following code:
[System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified, DataType="date")]
public System.DateTime time {
get {
return this.timeField;
}
set {
this.timeField = value;
}
}
When deserializing XML to objects using XmlSerializer all seems to be well. The problem I am facing is that the service expects dates to be formatted as YYYY-MM-DD hh:mm:ss and the XSD generated code seems to produce only YYYY-MM-DD.
If I modify XSD manually to xs:dateTime type, the generated C# code produces: 2010-08-20T20:07:03.915039Z.
Basically, how do I force serialization to produce YYYY-MM-DD hh:mm:ss? Is there something to do to XSD or is there something I can do to alter generated C# code?
In the past, I've done the following to control datetime serialization:
Ignore the DateTime property.
Create a dummy string property that serializes/deserializes the way I want
Here is an example:
public class SomeClass
{
[XmlIgnore]
public DateTime SomeDate { get; set; }
[XmlElement("SomeDate")]
public string SomeDateString
{
get { return this.SomeDate.ToString("yyyy-MM-dd HH:mm:ss"); }
set { this.SomeDate = DateTime.Parse(value); }
}
}
Use [XmlElement(DataType = "date")] attribute to format your DateTime property value as you need.
From MSDN:
Note:
The attribute that annotates the publicationdate field has a
DataType property. There is no type in the .NET Framework that matches
the type xs:date completely. The closest match is System.DateTime,
which stores date and time data. Specifying the DataType property as a
"date" ensures that the XmlSerializer will only serialize the date
part of the DateTime object.
If you only need to clear out the millisecond part. Refer to:
How to truncate milliseconds off of a .NET DateTime
And basicly do something like:
startDateTimeToUse = startDateTimeToUse.AddTicks(-(startDateTimeToUse.Ticks % TimeSpan.TicksPerSecond));
endDate = endDate.AddTicks(-(endDate.Ticks % TimeSpan.TicksPerSecond));
I can confirm that this serializes to:
<startDate>2015-10-31T12:13:04</startDate>
<endDate>2016-11-10T12:13:06</endDate>
I must also state that Before clearing the milliseconds I'm doing this:
var startDateTimeToUse = ssStartDateTime.ToUniversalTime();
var endDate = DateTime.Now.ToUniversalTime();
startDateTimeToUse = DateTime.SpecifyKind(startDateTimeToUse, DateTimeKind.Unspecified);
endDate = DateTime.SpecifyKind(endDate, DateTimeKind.Unspecified);
Which I don't know if it's having any effect on the serialization or not at this point
I believe implementing IXmlSerializable interface will do a trick. You can then control how you serialize and deserialize your object.
see answers above but to add-- if you only wanted output when the value is non-null (e.g. XML maxOccurs=0) you can utilize something like this:
private System.DateTime? someDateField;
public string someDate
{
get
{
return someDateField?.ToString("MM-dd-yyyy");
}
set
{
dobField = System.DateTime.Parse(value);
}
}
I may have another option.
When setting your DateTime just subtract the number of ticks of everything after the seconds, like:
public DateTime Dt
{
get => _dt;
set
{
_dt = value;
long elapsedTicks = _dt.Ticks - new DateTime(_dt.Year, _dt.Month, _dt.Day, _dt.Hour, _dt.Minute, _dt.Second).Ticks;
TimeSpan elapsedSpan = new TimeSpan(elapsedTicks);
_dt = _dt.Subtract(elapsedSpan);
}
}
private DateTime _dt = default(DateTime);
That way when you serialize your DateTime (Dt) the milliseconds won't be used and you'll have a value hh:mm:ss, that is at least what it gave me. That way no need to modify anything inside your XML definition.

Categories

Resources