Flutter/Dart DateTime parsing UTC and converting to local - dart

I am trying to parse a UTC Date string to DateTime and then parse it to local, however I am having troubles with converting it to the local time. In the UK it should be plus one, however when I print .isUtc it returns as false.
This is what I have now:
print(widget.asset.purchaseDate);
DateTime temp = DateTime.parse(widget.asset.purchaseDate);
print(temp.toLocal());
I/flutter (5434): 2020-05-07 21:29:00
I/flutter (5434): 2020-05-07 21:29:00.000

You need to indicate a timezone to DateTime.parse, otherwise it assumes local time. From the dartdoc:
An optional time-zone offset part, possibly separated from the
previous by a space. The time zone is either 'z' or 'Z', or it is a
signed two digit hour part and an optional two digit minute part.
Since you know your string represents UTC, you can tell the parser by adding the Z suffix.
var temp = DateTime.parse(widget.asset.purchaseDate + 'Z');
print(temp.isUtc); // prints true

While #Richard Heap's answer stands I'd like DateTime.parseUtc() to exist.
If there will be a day when dart allows static extension methods here is an implementation that would work:
extension DateTimeExtension on DateTime {
static DateTime parseUtc(String formattedDate) => DateTime.parse('${formattedDate}z');
static DateTime? tryParseUtc(String? formattedDate) {
if (formattedDate != null) {
return DateTime.tryParse('${formattedDate}z');
}
return null;
}
}
Currently you'd have to use it with the extension classes name, like so:
DateTimeExtension.parseUtc(someDate)
or
DateTimeExtension.tryParseUtc(someOtherDate)
I think the latter is more useful where someOtherDate is nullable

Related

How to give a date Format to the sting parameter in query string? [duplicate]

I have to convert string in mm/dd/yyyy format to datetime variable but it should remain in mm/dd/yyyy format.
string strDate = DateTime.Now.ToString("MM/dd/yyyy");
Please help.
You are looking for the DateTime.Parse() method (MSDN Article)
So you can do:
var dateTime = DateTime.Parse("01/01/2001");
Which will give you a DateTime typed object.
If you need to specify which date format you want to use, you would use DateTime.ParseExact (MSDN Article)
Which you would use in a situation like this (Where you are using a British style date format):
string[] formats= { "dd/MM/yyyy" }
var dateTime = DateTime.ParseExact("01/01/2001", formats, new CultureInfo("en-US"), DateTimeStyles.None);
You need an uppercase M for the month part.
string strDate = DateTime.Now.ToString("MM/dd/yyyy");
Lowercase m is for outputting (and parsing) a minute (such as h:mm).
e.g. a full date time string might look like this:
string strDate = DateTime.Now.ToString("MM/dd/yyyy h:mm");
Notice the uppercase/lowercase mM difference.
Also if you will always deal with the same datetime format string, you can make it easier by writing them as C# extension methods.
public static class DateTimeMyFormatExtensions
{
public static string ToMyFormatString(this DateTime dt)
{
return dt.ToString("MM/dd/yyyy");
}
}
public static class StringMyDateTimeFormatExtension
{
public static DateTime ParseMyFormatDateTime(this string s)
{
var culture = System.Globalization.CultureInfo.CurrentCulture;
return DateTime.ParseExact(s, "MM/dd/yyyy", culture);
}
}
EXAMPLE: Translating between DateTime/string
DateTime now = DateTime.Now;
string strNow = now.ToMyFormatString();
DateTime nowAgain = strNow.ParseMyFormatDateTime();
Note that there is NO way to store a custom DateTime format information to use as default as in .NET most string formatting depends on the currently set culture, i.e.
System.Globalization.CultureInfo.CurrentCulture.
The only easy way you can do is to roll a custom extension method.
Also, the other easy way would be to use a different "container" or "wrapper" class for your DateTime, i.e. some special class with explicit operator defined that automatically translates to and from DateTime/string. But that is dangerous territory.
Solution
DateTime.Now.ToString("MM/dd/yyyy", CultureInfo.InvariantCulture)
I did like this
var datetoEnter= DateTime.ParseExact(createdDate, "dd/mm/yyyy", CultureInfo.InvariantCulture);
You can change the format too by doing this
string fecha = DateTime.Now.ToString(format:"dd-MM-yyyy");
// this change the "/" for the "-"
The following works for me.
string strToday = DateTime.Today.ToString("MM/dd/yyyy");

How to parse a String of "hh:mm:ss.SSS" into a DateTime

The format of "new DateTime.now()" will print following output:
2015-05-20 07:34:43.018
By having only the time as a String in the correct format ("07:34:43.018"), how do I parse the time to a DateTime object? The usage of the intl package does not support the mentioned format AFAIK.
By prefixing the Date in front of the time, DateTime would be able to parse the given String.
DateTime parse(String timeValue) {
var prefix = '0000-01-01T';
return DateTime.parse(prefix + timeValue);
}
If you also only want to display the time afterwards, format your DateTime variable accordingly:
String format(DateTime value) {
return "${value.hour}:${value.minute}:${value.second}.${value.millisecond}";
}
I've mainly had to parse the String for calculations (difference) with other time values.

datetime utc handling with DateTimeZoneHandling

i am trying to figure out why my dates on the client are different than my dates on the server... down below i have a breezeconfig class that i thought would allow my server side "unspecified" dates to be serialized as "utc"... however a date of "2011-08-11" is still being serialized as "2011-08-11T00:00:00.000" which i believe is missing the "Z" at the end in order to signify utc... any ideas? thank you
public class BreezeConfig : Breeze.WebApi.BreezeConfig
{
protected override Newtonsoft.Json.JsonSerializerSettings CreateJsonSerializerSettings()
{
var ret = base.CreateJsonSerializerSettings();
ret.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
return ret;
}
}
Setting ret.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc; doesn't work as expected because ret created by the base Breeze.WebApi.BreezeConfig.CreateJsonSerializerSettings() adds IsoDateTimeConverter to the ret.Converters list. By default IsoDateTimeConverter will not add 'Z' to the output string if DateTime.Kind is DateTimeKind.Unspecified. Like Jay Trabant answered -
breeze.js fixes this client-side.
With this knowledge it's ease to make your server return all dates as UTC:
var isoDateTimeConverter = ret.Converters.OfType<Newtonsoft.Json.Converters.IsoDateTimeConverter>().Single();
isoDateTimeConverter.DateTimeStyles = System.Globalization.DateTimeStyles.AssumeUniversal;
Because there is a bug in IsoDateTimeConverter - Issue with DateTimeStyles, it's better to completely remove IsoDateTimeConverter from the Converters collection and set DateTimeZoneHandling to Utc:
public class CustomBreezeConfig : Breeze.ContextProvider.BreezeConfig
{
protected override Newtonsoft.Json.JsonSerializerSettings CreateJsonSerializerSettings()
{
var settings = base.CreateJsonSerializerSettings();
settings.DateTimeZoneHandling = Newtonsoft.Json.DateTimeZoneHandling.Utc;
var isoDateTimeConverter = settings.Converters.OfType<Newtonsoft.Json.Converters.IsoDateTimeConverter>().Single();
settings.Converters.Remove(isoDateTimeConverter);
return settings;
}
}
My guess is that your server datatype is a DateTime ( not a DateTime2 or DateTimeOffset), and as such has no explicit timezone information.
Breeze does not manipulate the datetimes going to and from the server in any way EXCEPT to add a UTZ timezone specifier to any dates returned from the server that do not already have one. This is only done because different browsers interpret dates without a timezone specifier differently and we want consistency between browsers.
This is discussed in more detail in the answer posted here. breezejs: date is not set to the right time

Golang XML Unmarshal and time.Time fields

I have XML data I am retrieving via a REST API that I am unmarshal-ing into a GO struct. One of the fields is a date field, however the date format returned by the API does not match the default time.Time parse format and thus the unmarshal fails.
Is there any way to specify to the unmarshal function which date format to use in the time.Time parsing? I'd like to use properly defined types and using a string to hold a datetime field feels wrong.
Sample struct:
type Transaction struct {
Id int64 `xml:"sequencenumber"`
ReferenceNumber string `xml:"ourref"`
Description string `xml:"description"`
Type string `xml:"type"`
CustomerID string `xml:"namecode"`
DateEntered time.Time `xml:"enterdate"` //this is the field in question
Gross float64 `xml:"gross"`
Container TransactionDetailContainer `xml:"subfile"`
}
The date format returned is "yyyymmdd".
I had the same problem.
time.Time doesn't satisfy the xml.Unmarshaler interface. And you can not specify a date fomat.
If you don't want to handle the parsing afterward and you prefer to let the xml.encoding do it, one solution is to create a struct with an anonymous time.Time field and implement your own UnmarshalXML with your custom date format.
type Transaction struct {
//...
DateEntered customTime `xml:"enterdate"` // use your own type that satisfies UnmarshalXML
//...
}
type customTime struct {
time.Time
}
func (c *customTime) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
const shortForm = "20060102" // yyyymmdd date format
var v string
d.DecodeElement(&v, &start)
parse, err := time.Parse(shortForm, v)
if err != nil {
return err
}
*c = customTime{parse}
return nil
}
If your XML element uses an attribut as a date, you have to implement UnmarshalXMLAttr the same way.
See http://play.golang.org/p/EFXZNsjE4a
From what I have read the encoding/xml has some known issues that have been put off until a later date...
To get around this issue, instead of using the type time.Time use string and handle the parsing afterwards.
I had quite a bit of trouble getting time.Parse to work with dates in the following format: "Fri, 09 Aug 2013 19:39:39 GMT"
Oddly enough I found that "net/http" has a ParseTime function that takes a string that worked perfectly...
http://golang.org/pkg/net/http/#ParseTime
I've implemented a xml dateTime format conforming a spec, you can find it on GitHub: https://github.com/datainq/xml-date-time
You can find XML dateTime in W3C spec
A niche technique to override the JSON marshaling/unmarshaling of select keys in a struct is also applicable to XML marshaling/unmarshaling, with minimal modifications. The idea remains the same: Alias the original struct to hide the Unmarshal method, and embed the alias in another struct where individual fields may be overridden to allow the default unmarshaling method to apply.
In your example, following the idea above, I'd do it like this:
type TransactionA Transaction
type TransactionS struct {
*TransactionA
DateEntered string `xml:"enterdate"`
}
func (t *Transaction) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
const shortForm = "20060102" // yyyymmdd date format
var s = &TransactionS{TransactionA: (*TransactionA)(t)}
d.DecodeElement(s, &start)
t.DateEntered, _ = time.Parse(shortForm, s.DateEntered)
return nil
}
The smartest point of this method is, by sending TransactionS into DecodeElement, all fields of t gets populated through the embedded alias type *TransactionA, except for those overridden in the S-type. You can then process overridden struct members as you wish.
This approach scales very well if you have multiple fields of different types that you want to handle in a custom way, plus the benefit that you don't introduce an otherwise useless customType that you have to convert over and over again.
const shortForm = "20060102" // yyyymmdd date format
It is unreadable. But it is right in Go. You can read the source in http://golang.org/src/time/format.go

How to order by time and time only in C#?

I have this recorded in SQL Server:
1- startTime (datetime): 5/2/2009 08:30 (brazilian time format: d/m/y)
2- startTime (datetime): 4/2/2009 14:30 (brazilian time format: d/m/y)
My application just records time... the date it's SQL that generates by itself be getting the date of today.
When I ask VS 2008 to order this datetime fields, it returns me that code #2 is before #1, because 4/2/2009 comes before 5/2/2009.
But, actually I want it to order by time only and ignore the date.
Is it possible??
Thanks!!
André
from d in dates
orderby d.TimeOfDay
select d;
or
dates.OrderBy(d => d.TimeOfDay);
Note: This will work as long as this is plain LINQ and not LINQ-to-SQL. If you're using LINQ-to-SQL to query your database, you'll need something that will translate to SQL.
You might also try fixing your app so it always saves the same base date with the time (like '01/01/1900' or whatever) and then you do not have to do all these slow and inefficient date stripping operations every time you need to do a query.
Or as Joel said, truncate or strip off the date portion before you do the insert or update.
Well, you can't really store a datetime without a date, but you could just store the total seconds as an double (using #florian's method).
You'd have to add a second method to convert this back to a date in your object, if you still need a date, such as:
public class BusinessObjectWithDate
{
private string _someOtherDbField = "";
private double _timeInMS = 0; // save this to the database
// sort by this? in sql or in code. You don't really need this
// property, since TimeWithDate actually saves the _timeInMS field
public double TimeInMS {
get { return _timeInMS; }
}
public DateTime TimeWithDate { // sort by this too, if you want
get { return (new DateTime(1900,1,1).AddMilliseconds(_timeInMS)); }
set { _timeInMS = value.TimeOfDay.TotalMilliseconds; }
}
}
var f = new BusinessObjectWithDate();
MessageBox.Show( f.TimeWithDate.ToString() ); // 1/1/1900 12:00:00 AM
f.TimeWithDate = DateTime.Now;
MessageBox.Show( f.TimeWithDate.ToString() ); // 1/1/1900 1:14:57 PM
You could also just store the real date time, but always overwrite with 1/1/1900 when the value gets set. This would also work in sql
public class BusinessObjectWithDate
{
private DateTime _msStoredInDate;
public DateTime TimeWithDate
{
get { return _msStoredInDate; }
set {
var ms = value.TimeOfDay.TotalMilliseconds;
_msStoredInDate = (new DateTime(1900, 1, 1).AddMilliseconds(ms));
}
}
}
Try this in your sql:
ORDER BY startTime - CAST(FLOOR(CAST(startTime AS Float)) AS DateTime)

Resources