Parsing Timex Expressions in .NET Core - c#

Using LUIS engine, I receive XXXX-10-28 as a date in the Entity Value.
I've tried using Chronic to parse but Chronic does not work with timex library/formats.
I'm expecting following strings as inputs
XXXX-10-28 should equate to 2018-10-28 (future)
2018-10-02TMO should equate to 2018-10-02 i.e. tomorrow
Please note that XXXX-XX represents YYYY-MM but it doesn't have numeric values
Is there any library, or way to parse such strings to a valid datetime format in ASP.NET Core?

You can use the Microsoft.Recognizers.Text.DataTypes.TimexExpression package from NuGet. It's part of the Microsoft Recognizers Text project here on github
I found two ways you can use this library:
Parse the expression using a TimexProperty and guess the year yourself:
var parsed = new Microsoft.Recognizers.Text.DataTypes.TimexExpression.TimexProperty("XXXX-10-28");
Console.WriteLine(parsed.Year); // = null
Console.WriteLine(parsed.Month); // = 28
Console.WriteLine(parsed.DayOfMonth); // = 10
Resolve times useing the TimexResolver
var resolution = Microsoft.Recognizers.Text.DataTypes.TimexExpression.TimexResolver.Resolve(new [] { "XXXX-10-28" }, System.DateTime.Today)
The resolution.Values will contain an array with two resolution entries, one for the previous occurrence of that date and one for the next occurrence of that date (based on the DateTime you pass into the Resolve method.
Note that from personal experience and from what I saw on github, that at the time of writing, this package can be quite buggy with the more advanced expressions.

Use a custom format pattern:
using System;
using System.Globalization;
class MainClass {
public static void Main (string[] args) {
var format = "1234-10-30";
var date = DateTime.ParseExact(format, "yyyy-MM-dd", CultureInfo.InvariantCulture);
Console.WriteLine (date.ToString("dd/MM/yyyy"));
}
}
Example

You can use DateTime.TryParse or DateTime.TryParseExact along with a custom date/time format string in order to accomplish this.
Based on your example, I think the format string you'd want is yyyy-MM-dd, although you may need to tweak this slightly.
Example:
var input = "2018-10-28";
var format = "yyyy-MM-dd";
DateTime parsed;
if (DateTime.TryParseExact(input, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out parsed))
{
// Do whatever you want with "parsed"
}

Related

Parsing Dates using JSON.NET

I am using JSON.NET's LINQ to JSON to parse data, which includes dates. My sample JSON looks like this:
{"2013" : [
{ "date":"2/5/2013 11:13 AM","id":23 }],
"2012" : [
{ "date":"28/9/2012 5:29 PM","id":24 }]
}
The format of the date is in d/m/yyyy h:mm. I tried parsing it first using DateTime.Parse:
var postTitles = jobject.Children().SelectMany(x => x.First).
Select(p =>
new Report
{
Date = DateTime.Parse((string)p["date"]),
Height = (int)p["height"]
});
However, it throws a FormatException on the second date so I tried using DateTime.ParseExact instead:
var postTitles = jobject.Children().SelectMany(x => x.First).
Select(p =>
new Report
{
Date = DateTime.ParseExact(p["date"].ToString(), "dd/mm/yyyy hh:mm", new
CultureInfo("en-US")),
Height = (int)p["height"]
});
This time, I get a FormatException on the first date. Are there any alternatives on how to parse this dates? I tried using Extension Methods as I am used to doing XML but it seems my extension methods are not recognized.
Your format string for ParseExact is very broken. Basically, you really need to pay attention to the format of your actual data, and look at the MSDN documentation for custom date/time strings. You can't just put any old pattern in and expect it to work: it's got to match your data.
So you probably want a format string of "d/M/yyyy h:mm tt". I would also suggest using the invariant culture:
Date = DateTime.ParseExact(p["date"].ToString(), "d/M/yyyy h:mm tt",
CultureInfo.InvariantCulture);
(The invariant culture is mostly the same as the US culture, but the important aspect is that it indicates that this is intended for machine-generated data rather than genuinely US-centric data.)
There may well be a better way of doing this in JSON.NET, but that should at least be a starting point.

C# Formatting DateTime giving me wrong result

I'm trying to format a DateTime in a C# function, but I can't get it to work.
The format I'm trying to get is like this:
"28/02/2012"
I've tried different ways to format the DateTime, for example:
string formattedDate = DateTime.Today.ToString("dd/MM/yyyy");
string formattedDate = String.Format("{0:dd/MM/yyyy}", DateTime.Today);
Both these examples are giving me this result:
"28.02.2012"
I've formatted DateTimes many times before using the two ways shown above, but I can't really see why I'm getting "." instead of "/".
Is there some configuration that has to be set up or something?
phoog has given the correct reason, but I would suggest the wrong workaround. If you always want to format the date/time as if you were in a particular culture (probably the invariant culture) then you can do that:
string formattedDate = DateTime.Today.ToString("dd/MM/yyyy",
CultureInfo.InvariantCulture);
I find this cleaner than forcing some parts of the format into an invariant form, while leaving others (the numbers) up to the culture. For example, consider this:
using System;
using System.Globalization;
using System.Threading;
class Test
{
static void Main()
{
CultureInfo ci = new CultureInfo("ar-SA");
Thread.CurrentThread.CurrentCulture = ci;
string formattedDate = DateTime.Today.ToString("dd/MM/yyyy");
Console.WriteLine(formattedDate);
}
}
Today, that prints "06/04/1433" - which is appropriate for the Islamic calendar, but probably isn't what you expected.
The / character in a date-time format string is a placeholder for the culture-specific date separator. To specify the / character explicitly, you need to escape it: "dd\\/MM\\/yyyy" or #"dd\/MM\/yyyy"
For more information, see the MSDN page "Custom Date and Time Format Strings"
I did it like this:
string formattedDate = (String.Format("{0:dd.MM.yyyy}", DateTime.Today)).Replace(".", #"/");

What is causing this behavior, in our C# DateTime type?

[Test]
public void Sadness()
{
var dateTime = DateTime.UtcNow;
Assert.That(dateTime, Is.EqualTo(DateTime.Parse(dateTime.ToString())));
}
Failed :
Expected: 2011-10-31 06:12:44.000
But was: 2011-10-31 06:12:44.350
I wish to know what is happening behind the scenes in ToString() etc to cause this behavior.
EDIT After seeing Jon's Answer :
[Test]
public void NewSadness()
{
var dateTime = DateTime.UtcNow;
Assert.That(dateTime, Is.EqualTo(DateTime.Parse(dateTime.ToString("o"))));
}
Result :
Expected: 2011-10-31 12:03:04.161
But was: 2011-10-31 06:33:04.161
Same result with capital and small 'o' . I'm reading up the docs, but still unclear.
Have a look at what dateTime.ToString() produces - it will typically only be accurate to the second, although it depends on cultural settings. If ToString() only gives a result accurate to a second, there's no way that parsing the string can give more information...
You can use the "o" standard format string to provide a round-trippable string representation. For example, at the moment it produces something like:
2011-10-31T06:28:34.6425574Z
EDIT: You need to parse with the same specifier to get the same result back:
string text = dateTime.ToString("o");
// Culture is irrelevant when using the "o" specifier
DateTime parsed = DateTime.ParseExact(text, "o", null,
DateTimeStyles.RoundtripKind);
The default format specifier is "G" - the general-purpose format - which has limited fidelity. If you want to reproduce exactly the same thing, use the roundtrip specifier, "O".
string s = dateTime.ToString("O", CultureInfo.InvariantCulture);
Assert.That(dateTime, Is.EqualTo(DateTime.ParseExact(
s, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind)));

DateTime FormatException error

DateTime datuMDokumenta = Convert.ToDateTime(txtDatumDokum.Text);
txtDatumDokum.Text is like "09.09.2011".
but i get FormatException error. Must i parse date?
Try DateTime.ParseExact with the dd.MM.yyyy format string
DateTime.ParseExact(txtDatumDokum.Text, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None);
It's not good to see, anyway try this:
string s = "09.09.2011";
DateTime dt = Convert.ToDateTime(
s.Replace(".",
new System.Globalization.DateTimeFormatInfo().DateSeparator));
You need to tell us why the text input is using this format. If it is because the user enters it this way, then you need to make sure that the format matches that given by Thread.CurrentCulture.DateTimeFormat.ShortDatePattern. Changing the culture (by setting
Thread.CurrentCulture) to an appropriate value will then solve your problem.
If you are supposed to parse the input no matter what format it is in, then you will need to do some manual processing first (perhaps remove spaces and other delimiter characters from the input with string.Replace) and then try to parse the date using DateTime.ParseExact and a known format string.
But it all depends on why the input has that format, and why your application's current culture does not match it.
You could try this, TryParse avoids parsing exceptions.. Then you just need check result to be sure that it parsed.
DateTime datuMDokumenta;
bool result = DateTime.TryParse(txtDatumDokum.Text, out datuMDokumenta);
You will have to determine if this is a good solution for your application.
See this example:
http://msdn.microsoft.com/en-us/library/ch92fbc1.aspx
Judging by the date you gave you need to include a culture, de-DE accepts 01.01.11 type of dates but I'm not sure which one you actually want to use, you'll need to decide that.. the Code would look like this:
using System.Globalization;
DateTime datuMDokumenta;
bool result = DateTime.TryParse(txtDatumDokum.Text, CultureInfo.CreateSpecificCulture("de-DE"), DateTimeStyles.None, out datuMDokumenta);
A list of cultures can be found here, select the appropriate one for you:
http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo%28v=vs.71%29.aspx
The plus here is that this code is a bit more work but it is very difficult to break. Assuming you are using a free text entry on a TextBox you don't want to be throwing exceptions.
Yes you have to parse input date in current culture.
string[] format = new string[] { "dd.MM.yyyy" };
string value = "09.09.2011";
DateTime datetime;
if (DateTime.TryParseExact(value, format, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.NoCurrentDateDefault, out datetime))
//Valid
else
//Invalid
DateTime dt = Convert.ToDateTime(txtDatumDokum.Text)
It is right...there is no isssue
During a Deserialization call under compact framework 3.5 i've had some unexpected behaviour before.
I've converted from using the OpenNETCF serialization classes to the framework XML serialization class. In doing so, the default time format has changed and the order of property/public members. So long story short, i've exposed a text property which converts my date-times back to the format my VB6 application is expecting.
Dim dumbDate As New Date
Dim formats() As String = {"yyyy-MM-ddTHH:mm:ss.fffzzz", _
"yyyy-MM-dd HH:mm:ss:fffffffzzz"}
_datetimeTaken = dumbDate.ParseExact(value, formats, CultureInfo.InvariantCulture, DateTimeStyles.None)
' There is something wrong with compact framework during the Serialization calls.
' calling the shared method Date.Parse or Date.ParseExact does not produce the same
' result as calling a share method on an instance of Date. WTF?!?!?!
' The below will cause a "Format" exception.
'_datetimeTaken = Date.ParseExact(value, formats, CultureInfo.InvariantCulture, DateTimeStyles.None)
Date.blah doesn't work. dumbDate.blah works. strange.
public static void Main(string[] args)
{
var dt = new DateTime(2018, 04, 1);
Console.WriteLine(dt);
string month = dt.ToString("MMMM");
Console.WriteLine(month); //April
month = dt.ToString("MMM");
Console.WriteLine(month); //Apr
month = dt.ToString("MM");
Console.WriteLine(month); //04
Console.ReadKey();
}
your code:
DateTime datuMDokumenta = Convert.ToDateTime(txtDatumDokum.Text);
try changing this to:
DateTime datuMDokumenta = Convert.ToDateTime(txtDatumDokum);
and when u print the date/time
print datuMDokumenta.Text

How to convert any type of date to dd/mm/yyyy

I receive text from a *.csv file in any date format
For example: dd/mm/yy or dd/mm/yyyy or mm/dd/yyyy or 4 may 2010......
How I can convert to just a single type of format: dd/mm/yyyy ?
I'm working on C#, .NET 3.5, WinForms
Thanks in advance
If you're receiving data in multiple formats and you can't identify them, you've got problems. What does "09/07/2010" mean? September 7th or July 9th? This is the first thing to get straight in your mind, and it has nothing to do with technology. You have two contradictory formats - how are you going to deal with them? Sample the file and pick whichever looks most likely? Treat each line separately, favouring one format over another? Ask the user?
Once you've parsed the data correctly, formatting it in the desired way is easy, as per John's answer. Note that you must use "MM" for the month, not "mm" which represents minutes. You should also specify which culture to use (affecting the date separators) assuming you don't just want to take the system default.
DateTime.Parse("your data").ToString("dd/MM/yyyy");
Check out TryParseExact.
public static string FormatDate(string input, string goalFormat, string[] formats)
{
var c = CultureInfo.CurrentCulture;
var s = DateTimeStyles.None;
var result = default(DateTime);
if (DateTime.TryParseExact(input, formats, c, s, out result))
return result.ToString(goalFormat);
throw new FormatException("Unhandled input format: " + input);
}
Example Usage
var formats - new[] { "dd/MM/yy", "dd/MM/yyyy" };
var next = csvReader.Get("DateField");
var formattedDate = FormatDate(next, "dd/MM/yyyy", formats);
using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
namespace dateconvert
{
class Program
{
static void Main(string[] args)
{
DateTime x = Convert.ToDateTime("02/28/10");
Console.WriteLine(string.Format(x.ToString("d", DateTimeFormatInfo.InvariantInfo)));
DateTime y = Convert.ToDateTime("May 25, 2010");
Console.WriteLine(string.Format(y.ToString("d", DateTimeFormatInfo.InvariantInfo)));
DateTime z = Convert.ToDateTime("12 May 2010");
Console.WriteLine(string.Format(z.ToString("d", DateTimeFormatInfo.InvariantInfo)));
Console.Read();
}
}
}
String.Format("{0:MM/dd/yyyy}", DateTime.Now);
String.Format("{0:dd/MM/yyyy}", DateTime.Now);
etc.
Source: http://www.csharp-examples.net/string-format-datetime/
You simply want to be using the DateTime.ParseExact together with the DateTime.ToString methods.
The straight DateTime.Parse method has its uses of course, and can be clever for parsing dates that you know are in a specific culture/locale, but since it seems dates given to you may be in an arbitrary format that cannot be recognised, you may want to specifically use ParseExact.
Example:
var myDate = DateTime.ParseExact("07/14/2010", "MM/dd/yyyy",
CultureInfo.CurrentCulture);
var standardDateString = myDate.ToString("dd/MM/yyyy");

Categories