Understanding the time.Parse function in Go - c#

I am currently porting code from go to c# and came across this (simplified) piece of code.
I do know that it converts a given string 171228175744.085 using a given format 060102150405.
The official docs only have examples using common formats like 2017-Feb-1, not this format (a possible timestamp?)
I do know that this will result in the time beeing 2017-12-28 17:57:44.085 +0000 UTC, but I do not have a clue how, because I have no information what the string 171228175744.085 and layout represent. I do know that some of this information is GPS related. So, my question is: Does anyone know how to do this in c#?
package main
import (
"fmt"
"time"
)
func main() {
t, err := time.Parse("060102150405", "171228175744.085")
if err == nil{
fmt.Println(t)
}
}

The docs around time.Format explain what the format means.
Quoting:
Format returns a textual representation of the time value formatted
according to layout, which defines the format by showing how the
reference time, defined to be
Mon Jan 2 15:04:05 -0700 MST 2006
The format string in your example: 060102150405 tells the time parser to look for the following:
06: year
01: month
02: day of the month
15: hour of the day
04: minute
05: second
This is a convenient way of telling the parser how it should interpret each number. If you look carefully, you'll see that numbers are not reused so when you say 06, the parser matches it to 2006.
In C#, you can use datetime.ParseExact. Something along the lines of:
DateTime.ParseExact(dateString, "yyMMddhhmmss", some_provider);
(note: I have not tried the C# snippet above. You may need to adjust it)

Related

How do I format a single digit month in C# date formatting?

In C#, if I run this code, it prints out 05:
Console.WriteLine(DateTime.Now.ToString("MM"));
However, if I run this code, it prints out May 16:
Console.WriteLine(DateTime.Now.ToString("M"));
I'm looking for a date format that will print out 5. How do I format a single digit month? To be clear, it would be 1 digit for months 1 to 9, and 2 digits for months 10 to 12.
“%M" should work. See custom format strings
Some explanation:
The "M" can be part of a custom format string, where it means a "month number" in one or two digits
But on itself it can also be a standard format string meaning a "month day pattern" - as the OP found out.
To resolve this ambiguity you can add a space, which makes it a custom format string, but also adds a space to the resulting value. Or you can add a %.
Right now (May) a DateTime.Now.ToString("%M") results in "5".
Microsoft has some excellent documentation regarding how to format DateTime as string values over at https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
The parameter you're looking for is M which would make the method call DateTime.Now.ToString("M");.
Update:
However, as pointed ut by Hans Kesting, this could give unexpected results in some situations which can be avoided by using a % in combination with the M as described at https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings#UsingSingleSpecifiers

Convert user given date (January or 01. February 2017) to a timestamp

i'm trying to parse a user input of a date to a MySQL Timestamp format (YYYY-MM-DD).
User input could be something like:
input - wanted conversion
1) January - ThisYear-01-01, ThisYear-01-31
2) February 2017 - 2017-02-01, 2017-02-28
3) 01. April 2016 - 2016-04-01
4) 5.4.15 - 2015-04-05
P.S.:
The examples above are the suggested formats that we want to support (supporting only some of them would be also fine).
The users are not random or international, they will always write and understand dates in this format (Day Month Year).
Handling the missing year entry or the zero (like 5/4 in #4) isn't a problem but finding a proper way to handle the mentioned possible date input formats (DD MM YY, DD MM, DD Month, Month, Month YY, DD Month YY....etc.) with something that doesn't look very ugly and long in code is a little bit hard for me to imagine.
P.S.:
D,DD,MM,YY,YYYY are short for the numerical input.
Month is for the word input variant.
Could you please tell me if there is anything that could help me to make this process easier/more readable or at least point me to the right direction?
Thanks
Update #1:
By looking again to my question above i see that it's missing some background information, but i didn't want to write a long description to it, just only to the wanted function. Sorry.
So here are some general infos about the Program:
The Program is a Chatbot written in C# (UWP) which accepts a user request in natural language and give back the requested info (if recognized) from a mySQL DB (DB is based on a OSTicket support system).
Internally we send the user input to LUIS.ai to get it recognized and we get back the intents and entities from the service, which we then parse to a SQL Query and send it to the DB.
The results from the DB are then sent back to the user.
Many parsed queries work perfectly, that's why i want now to extend it by letting the user give a certain date in the request (e.g. give me all the support tickets from April).
What i only want is to take this new input "April" and convert it to a MySQL TimeStamp format, so that it would be also recognized from MySQL.
My current approach is to build a string like this:
string convertedTS = year + "-" + month + "-" + day;
And using 3 functions try to detect all three variables. But that's it for now.
E.g. "give me all the tickets from April":
April (recognized from LUIS AI as given date) will be converted to (04)
Year will be taken from
DateTime.Today.Year
and inserted too (2018-04)
The first day is always 01 and the last day of the month will be:
DateTime.Today.Year
Final Query from the example:
select ..........between '2018-04-01' AND '2017-04-30'
If you're worried about formatting the years, months, days, etc, you're doing it wrong. You have C#, and you have a date string from the user. Your concern is getting that string into a C# DateTime value. MySql has no part of this.
Once you have the DateTime value, let your connection provider worry about formatting via parameterized queries:
DateTime d = GetMyDateTimeValueFromUser();
string sql = "pretend SQL comnand with a datetime #variable";
using (var cn = new MySqlConnection("connection string here"))
using (var cmd = new MySqlCommand(sql, cn))
{
cmd.Parameters.Add("#variable", MySqlDbType.Timestamp).Value = d;
cn.Open();
//pick one.
cmd.ExecuteReader();
cmd.ExecuteNonQuery();
}
No special SQL format needed. If you're not using parameterized queries, you're not doing it right! This applies to much more than just DateTime values. All data used in an SQL statement should be handled this way. This has security and performance implications that go way beyond simple date values. Go parameters, or go home (I mean that: go home. Don't write bad code. We don't need any more.)
As it applies to the question, it means the problem is entirely about parsing a string to a C# DateTime value. The next step of moving this data to SQL is just not relevant. Thankfully, .Net has some options for you here. Specifically, take a look at the Parse family of functions, including:
DateTime.Parse()
DateTime.TryParse()
DateTime.ParseExact()
DateTime.TryParseExact()
The latter two allow you specify a set of allowed formats that can match the formats actually seen by your system. NuGet can be a further resource in this area.
What's that, you say? You want to allow the user to input anything? That just won't work. Period. Real humans can and will come up with far more ways to enter a date than you could possibly ever handle. Not to mention you need to know what to do when a British citizen inputs the value 1/2/2018 into your system, because that person almost certainly believes it means February 1, 2018, and not January 2. Cultural differences like this mean it is impossible to accept date inputs without some kind of contextual input filter on the front end. You must look to your user interface to help your users create values your code will understand... but we don't have enough info in the question to provide any guidance yet in that area.
I fixed that for the purpose of using it in my program.
Now i can detect and understand such inputs:
"09 11 2008"
"2017"
"today"
"yesterday"
"09/11/2002"
"march 2017"
"01.01.2010"
"01-01-2010"
"01 may 2019"
"31.October 2020"
"01 april"
"december"
If anyone is also interested in writing a similar function leave a comment, because the code is almost 300 lines.

JSON: DateTimes deserialized format inconsistent [duplicate]

I've seen so many different standards for the JSON date format:
"\"\\/Date(1335205592410)\\/\"" .NET JavaScriptSerializer
"\"\\/Date(1335205592410-0500)\\/\"" .NET DataContractJsonSerializer
"2012-04-23T18:25:43.511Z" JavaScript built-in JSON object
"2012-04-21T18:25:43-05:00" ISO 8601
Which one is the right one? Or best? Is there any sort of standard on this?
JSON itself does not specify how dates should be represented, but JavaScript does.
You should use the format emitted by Date's toJSON method:
2012-04-23T18:25:43.511Z
Here's why:
It's human readable but also succinct
It sorts correctly
It includes fractional seconds, which can help re-establish chronology
It conforms to ISO 8601
ISO 8601 has been well-established internationally for more than a decade
ISO 8601 is endorsed by W3C, RFC3339, and XKCD
That being said, every date library ever written can understand "milliseconds since 1970". So for easy portability, ThiefMaster is right.
JSON does not know anything about dates. What .NET does is a non-standard hack/extension.
I would use a format that can be easily converted to a Date object in JavaScript, i.e. one that can be passed to new Date(...). The easiest and probably most portable format is the timestamp containing milliseconds since 1970.
There is no right format; The JSON specification does not specify a format for exchanging dates which is why there are so many different ways to do it.
The best format is arguably a date represented in ISO 8601 format (see Wikipedia); it is a well known and widely used format and can be handled across many different languages, making it very well suited for interoperability. If you have control over the generated json, for example, you provide data to other systems in json format, choosing 8601 as the date interchange format is a good choice.
If you do not have control over the generated json, for example, you are the consumer of json from several different existing systems, the best way of handling this is to have a date parsing utility function to handle the different formats expected.
When in doubt simply go to the javascript web console of a modern browser by pressing F12 (Ctrl+Shift+K in Firefox) and write the following:
new Date().toISOString()
Will output:
"2019-07-04T13:33:03.969Z"
Ta-da!!
From RFC 7493 (The I-JSON Message Format ):
I-JSON stands for either Internet JSON or Interoperable JSON, depending on who you ask.
Protocols often contain data items that are designed to contain
timestamps or time durations. It is RECOMMENDED that all such data
items be expressed as string values in ISO 8601 format, as specified
in RFC 3339, with the additional restrictions that uppercase rather
than lowercase letters be used, that the timezone be included not
defaulted, and that optional trailing seconds be included even when
their value is "00". It is also RECOMMENDED that all data items
containing time durations conform to the "duration" production in
Appendix A of RFC 3339, with the same additional restrictions.
Just for reference I've seen this format used:
Date.UTC(2017,2,22)
It works with JSONP which is supported by the $.getJSON() function. Not sure I would go so far as to recommend this approach... just throwing it out there as a possibility because people are doing it this way.
FWIW: Never use seconds since epoch in a communication protocol, nor milliseconds since epoch, because these are fraught with danger thanks to the randomized implementation of leap seconds (you have no idea whether sender and receiver both properly implement UTC leap seconds).
Kind of a pet hate, but many people believe that UTC is just the new name for GMT -- wrong! If your system does not implement leap seconds then you are using GMT (often called UTC despite being incorrect). If you do fully implement leap seconds you really are using UTC. Future leap seconds cannot be known; they get published by the IERS as necessary and require constant updates. If you are running a system that attempts to implement leap seconds but contains and out-of-date reference table (more common than you might think) then you have neither GMT, nor UTC, you have a wonky system pretending to be UTC.
These date counters are only compatible when expressed in a broken down format (y, m, d, etc). They are NEVER compatible in an epoch format. Keep that in mind.
"2014-01-01T23:28:56.782Z"
The date is represented in a standard and sortable format that represents a UTC time (indicated by the Z). ISO 8601 also supports time zones by replacing the Z with + or – value for the timezone offset:
"2014-02-01T09:28:56.321-10:00"
There are other variations of the timezone encoding in the ISO 8601 spec, but the –10:00 format is the only TZ format that current JSON parsers support. In general it’s best to use the UTC based format (Z) unless you have a specific need for figuring out the time zone in which the date was produced (possible only in server side generation).
NB:
var date = new Date();
console.log(date); // Wed Jan 01 2014 13:28:56 GMT-
1000 (Hawaiian Standard Time)
var json = JSON.stringify(date);
console.log(json); // "2014-01-01T23:28:56.782Z"
To tell you that's the preferred way even though JavaScript doesn't have a standard format for it
// JSON encoded date
var json = "\"2014-01-01T23:28:56.782Z\"";
var dateStr = JSON.parse(json);
console.log(dateStr); // 2014-01-01T23:28:56.782Z
JSON itself has no date format, it does not care how anyone stores dates. However, since this question is tagged with javascript, I assume you want to know how to store javascript dates in JSON. You can just pass in a date to the JSON.stringify method, and it will use Date.prototype.toJSON by default, which in turns uses Date.prototype.toISOString (MDN on Date.toJSON):
const json = JSON.stringify(new Date());
const parsed = JSON.parse(json); //2015-10-26T07:46:36.611Z
const date = new Date(parsed); // Back to date object
I also found it useful to use the reviver parameter of JSON.parse (MDN on JSON.parse) to automatically convert ISO strings back to javascript dates whenever I read JSON strings.
const isoDatePattern = new RegExp(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/);
const obj = {
a: 'foo',
b: new Date(1500000000000) // Fri Jul 14 2017, etc...
}
const json = JSON.stringify(obj);
// Convert back, use reviver function:
const parsed = JSON.parse(json, (key, value) => {
if (typeof value === 'string' && value.match(isoDatePattern)){
return new Date(value); // isostring, so cast to js date
}
return value; // leave any other value as-is
});
console.log(parsed.b); // // Fri Jul 14 2017, etc...
The prefered way is using 2018-04-23T18:25:43.511Z...
The picture below shows why this is the prefered way:
So as you see Date has a native Method toJSON, which return in this format and can be easily converted to Date again...
In Sharepoint 2013, getting data in JSON there is no format to convert date into date only format, because in that date should be in ISO format
yourDate.substring(0,10)
This may be helpful for you
I believe that the best format for universal interoperability is not the ISO-8601 string, but rather the format used by EJSON:
{ "myDateField": { "$date" : <ms-since-epoch> } }
As described here: https://docs.meteor.com/api/ejson.html
Benefits
Parsing performance: If you store dates as ISO-8601 strings, this is great if you are expecting a date value under that particular field, but if you have a system which must determine value types without context, you're parsing every string for a date format.
No Need for Date Validation: You need not worry about validation and verification of the date. Even if a string matches ISO-8601 format, it may not be a real date; this can never happen with an EJSON date.
Unambiguous Type Declaration: as far as generic data systems go, if you wanted to store an ISO string as a string in one case, and a real system date in another, generic systems adopting the ISO-8601 string format will not allow this, mechanically (without escape tricks or similar awful solutions).
Conclusion
I understand that a human-readable format (ISO-8601 string) is helpful and more convenient for 80% of use cases, and indeed no-one should ever be told not to store their dates as ISO-8601 strings if that's what their applications understand, but for a universally accepted transport format which should guarantee certain values to for sure be dates, how can we allow for ambiguity and need for so much validation?
it is work for me with parse Server
{
"ContractID": "203-17-DC0101-00003-10011",
"Supplier":"Sample Co., Ltd",
"Value":12345.80,
"Curency":"USD",
"StartDate": {
"__type": "Date",
"iso": "2017-08-22T06:11:00.000Z"
}
}
There is only one correct answer to this and most systems get it wrong. Number of milliseconds since epoch, aka a 64 bit integer. Time Zone is a UI concern and has no business in the app layer or db layer. Why does your db care what time zone something is, when you know it's going to store it as a 64 bit integer then do the transformation calculations.
Strip out the extraneous bits and just treat dates as numbers up to the UI. You can use simple arithmetic operators to do queries and logic.
The following code has worked for me. This code will print date in DD-MM-YYYY format.
DateValue=DateValue.substring(6,8)+"-"+DateValue.substring(4,6)+"-"+DateValue.substring(0,4);
else, you can also use:
DateValue=DateValue.substring(0,4)+"-"+DateValue.substring(4,6)+"-"+DateValue.substring(6,8);
I think that really depends on the use case. In many cases it might be more beneficial to use a proper object model (instead of rendering the date to a string), like so:
{
"person" :
{
"name" : {
"first": "Tom",
"middle": "M",
...
}
"dob" : {
"year": 2012,
"month": 4,
"day": 23,
"hour": 18,
"minute": 25,
"second": 43,
"timeZone": "America/New_York"
}
}
}
Admittedly this is more verbose than RFC 3339 but:
it's human readable as well
it implements a proper object model (as in OOP, as far as JSON permits it)
it supports time zones (not just the UTC offset at the given date and time)
it can support smaller units like milliseconds, nanoseconds, ... or simply fractional seconds
it doesn't require a separate parsing step (to parse the date-time string), the JSON parser will do everything for you
easy creation with any date-time framework or implementation in any language
can easily be extended to support other calendar scales (Hebrew, Chinese, Islamic ...) and eras (AD, BC, ...)
it's year 10000 safe ;-) (RFC 3339 isn't)
supports all-day dates and floating times (Javascript's Date.toJSON() doesn't)
I don't think that correct sorting (as noted by funroll for RFC 3339) is a feature that's really needed when serializing a date to JSON. Also that's only true for date-times having the same time zone offset.

Parsing dates without all values specified

I'm using free-form dates as part of a search syntax. I need to parse dates from strings, but only preserve the parts of the date that are actually specified. For instance, "november 1, 2010" is a specific date, but "november 2010" is the range of dates "november 1, 2010" to "november 30, 2010".
Unfortunately, DateTime.Parse and friends parse these dates to the same DateTime:
DateTime.Parse("November 1, 2010") // == {11/1/2010 12:00:00 AM}
DateTime.Parse("November, 2010") // == {11/1/2010 12:00:00 AM}
I need to know which parts of the DateTime were actually parsed and which were guessed by the parser. Essentially, I need DateTime.Parse("November, 2010") == {11/-1/2010 -1:-1:-1}; I can then see that the day portion is missing and calculate the range of dates covering the whole month.
(Internally, C# has the DateTimeParse and DateTimeResult classes that parse the date and preserve exactly the information I need, but by the time the date gets back to the public interfaces it's been stripped off. I'd rather avoid reflecting into these classes, unless that's really the only route.)
Is there some way to get DateTime.Parse to tell me which format it used to parse the date? Or can the returned DateTime have placeholders for unspecified parts? I'm also open to using another date parser, but I'd like it to be as reliable and locale-flexible as the internal one. Thanks in advance.
EDIT: I've also tried ParseExact, but enumerating all of the formats that Parse can handle seems nearly impossible. Parse actually accepts more formats than are returned by DateTimeFormatInfo.GetAllDateTimePatterns, which is about as canonical a source as I can find.
You could try using TryParseExact(), which will fail if the data string isn't in the exact format specified. Try a bunch of different combinations, and when one succeeds you know the format the date was in, and thus you know the parts of the date that weren't there and for which the parser filled in defaults. The downside is you have to anticipate how the user will want to enter dates, so you can expect exactly that.
You could also use a Regex to digest the date string yourself. Again, you'll need different regexes (or a REALLY complex single one), but it is certainly possible to pull the string apart this way as well; then you know what you actually have.
Parse parses a whole lot of stuff that no sane person would enter as a date, like "January / 2010 - 21 12: 00 :2". I think you'll have to write your own date parser if you want to know what exactly the user entered.
Personally I would do it like KeithS suggested: Parse the string with Parse and only call your own parse function if there's a 0 in one of the fields of the DateTime object. There are not that that possibilities you need to check for, because if the day is 0, the time will be 0, too. So start checking year, month, day, etc..
Or simply instruct the user to use specific formats you recognize.
Essentially, I need
DateTime.Parse("November, 2010") ==
{11/-1/2010 -1:-1:-1}; I can then see
that the day portion is missing and
calculate the range of dates covering
the whole month.
What you want is an illegal DateTime because you cannot have a negative hours/seconds/minute/day values. If you want to return something else other then a legal DateTime you have to write your own method which does NOT return a DateTime.
Is there some way to get
DateTime.Parse to tell me which format
it used to parse the date? Or can the
returned DateTime have placeholders
for unspecified parts? I'm also open
to using another date parser, but I'd
like it to be as reliable and
locale-flexible as the internal one.
Take a look here http://msdn.microsoft.com/en-us/library/w2sa9yss.aspx
You are going to have to manually keep track of what is entered to do this task. The only solution is to make sure the input is in the correct format.
I used this method that goes back to the original string in order to check for existence of the day and the year:
For days, the original string must contain a 1 as integer if the day was specified. So, split the string and look for a 1. The only exception occurs when the month is January (#1 month), so you should check for two 1s or a 1 and "January" or "Jan" in the original string.
For years, the original string must contain a number that can be a year (say, from 1900 to 2100). Other possibilities may be the use of an apostrophe, or things like 02-10-16, which you can recognize by the fact that there are exactly three numbers.
I know that this is pretty heuristic, but it's a fast and simple solution that works in most cases. I coded this algorithm in C# in the DateFinder.DayExists() and DateFinder.YearExists() methods in the sharp-datefinder library.

How to Convert date into MM/DD/YY format in C#

In My Asp.net webpage I need to display today's date into one of the textbox , so in my form load I wrote the following code
textbox1.text = System.DateTime.Today.ToShortDateString();
this line is giving me date like 1/7/09 but I want date like 01/07/09 , Is there anyway I can conver this date into mm/dd/yy format in C#?
DateTime.Today.ToString("MM/dd/yy")
Look at the docs for custom date and time format strings for more info.
(Oh, and I hope this app isn't destined for other cultures. That format could really confuse a lot of people... I've never understood the whole month/day/year thing, to be honest. It just seems weird to go "middle/low/high" in terms of scale like that.)
DateTime.Today.ToString("MM/dd/yy")
Look at the docs for custom date and time format strings for more info.
(Oh, and I hope this app isn't destined for other cultures. That format could really confuse a lot of people... I've never understood the whole month/day/year thing, to be honest. It just seems weird to go "middle/low/high" in terms of scale like that.)
Others cultures really are a problem. For example, that code in portugues returns someting like 01-01-01 instead of 01/01/01. I also don't undestand why...
To resolve that problem i do someting like this:
IFormatProvider yyyymmddFormat = new System.Globalization.CultureInfo(String.Empty, false);
return date.ToString("MM/dd/yy", yyyymmddFormat);
Have you tried the following?:
textbox1.text = System.DateTime.Today.ToString("MM/dd/yy");
Be aware that 2 digit years could be bad in the future...
Look into using the ToString() method with a specified format.
See, here you can get only date by passing a format string.
You can get a different date format as per your requirement as given below for current date:
DateTime.Now.ToString("M/d/yyyy");
Result : "9/1/2016"
DateTime.Now.ToString("M-d-yyyy");
Result : "9-1-2016"
DateTime.Now.ToString("yyyy-MM-dd");
Result : "2016-09-01"
DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss");
Result : "2016-09-01 09:20:10"
For more details take a look at MSDN reference for Custom Date and Time Format Strings

Categories

Resources