Date validation in Ballerina - datetime

I have to validate different types of dates in ballerina. I have been trying deal with it using regex, however there are many ways to write a date (eg. 25/05/2020, 05/25/2020, 25-May-2020 etc.).
It is hard to predict all the types. What's more, it would be nice to validate whether the received input is really a date - that includes different number of days in different months or leap years. Generally such regex would be monstrous (anyway really big). Are you aware of any existing library that would provide a shortcut or have date validation?
Is there any way to facilitate such task?

Validating all the date formats at a single go is a challenge, not only in Ballerina, but in the other languages too. Ballerina do not have a single method to validate all the date formats, but you can use ballerina/time library to parse date strings to Time records.
import ballerina/time;
public function main() {
string timeString = "<your time string>";
string timeFormat = "<your time format>";
time:Time|time:Error time = time:parse(timeString, timeFormat);
}
In the sample, the time:parse() will return a valid Time record, if the provided is a valid time, according to the provided time format.
I know this is not the exact answer you want, but this is the way to parse a time in Ballerina.
Alternatively, there are some Java answers which can be used (I am not sure whether they fulfil your requirement though) with Ballerina - Java interoperability.

Related

How can I get SignalR to stop changing my date/time values?

I have a simple class that contains a DateTime property. When I set the value of this property using DateTime.Now() the value is correct. However, when I pass this class object as a parameter via SignalR, on the receiving end SignalR has changed the DateTime so that it no longer matches the original DateTime. How can I get SignalR to stop manipulating my DateTime values? This issue seems to have started with a recent update to the latest SignalR nuget packages.
This seems to be a problem when the hub and the client are in two different time zones. It seems Microsoft is trying to help, by adjusting the date/time to the local time zone, but I want the original value, not the value Microsoft "thinks" I want.
When you want two systems to communicate with each other I would recommend using always the DateTime in UTC for various reasons. In your case you have two options here:
1 - Send the date as string string date = DateTime.Now.ToString(CultureInfo.InvariantCulture); so on the client side you just need to parse the datetime like DateTime.Parse(date, CultureInfo.InvariantCulture);.
2 - Send the date in UTC like DateTime.UtcNow; so event if the SignalR tries to change the date, it will have the DateTime.Kind as UTC. In this case or you will get the current date correctly, or you just adjust on the client side to the local time like receivedDate.ToLocalTime();
This one was a real head scratcher as I had the exact same issue. The client was storing the correct time but by the time it hit the Hub... it had changed. I'm really glad you posted this as I wouldn't have imagined this issue being possible. #Kiril1512 posted the correct resolution. In my case I used his second option as I didn't want to change my model... although simply converting to a string would have been simpler. While I did follow his suggestion and convert everything to DateTime.UtcNow()... I am thinking this was unnecessary as I noticed even previously stored dates converted correctly. This makes me think that either this isn't necessary to do, or dates are converted to Utc when they hit the Hub automatically which may be what the issue was to begin with?
Either way I posted this as I discovered that converting this date back to Local time was a little more involved. Here is how I ended up doing the conversion which resolved this issue for me that I gathered from this resource:
DateTime convertedDate = DateTime.SpecifyKind(
DateTime.Parse(msg.CreatedOn.ToString()),
DateTimeKind.Utc);
var kind = convertedDate.Kind;
DateTime dt = convertedDate.ToLocalTime();

spring.jackson.date-format add extra 4 hours to given input

I want to format java.util.Date.I get year month and day correctly but when I insert data to database I get 4 more hour.For example if I insert 2017-12-18 12:00
then inserted row will be 2017-12-18 16:00
My controller:
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String insertRequest(#RequestBody EmployeeRequest employeeRequest) {
System.out.println(employeeRequest.getDate());
requestService.insertRequest(employeeRequest);
return "inserted and sent mail";
}
My model :
#NotNull
private Date date;
My application.properties
spring.jackson.date-format=yyyy-MM-dd HH:mm
Thanks in advance
This is not a date formatting error, this is very likely related to TimeZone. Depending on how your Database and Application Server are configured it appears that they are using different default timezone's.
Have you tried reading the data back OUT of the database into Java? If the database is properly storing the timezone then it should Just Work when you read it back into your java object. If not, i'd suggest first updating your Date/Time format to include the timezone e.g. spring.jackson.date-format=yyyy-MM-dd HH:mm:ssZ. Then the database should at least have access to the appropriate timezone.
If this doens't work, the proper mitigation really depends on your application and how it needs to make use of time / timezones. It could be that what you have is actually fine, it's just that when you manually inspect the database it's displaying to you the time in the default timezone. You could also just set your database and app servers to use the same timezone, but this can be a configuration nightmare.
Side note: as some general advice, I'd high recommend using either java.time.* or jodatime libraries instead of java.util.Date if at all possible. This isn't related to this specific issue, but they are much more robust date/time libraries than the legacy java.util.Date

extract elasticsearch date from a <start-date>/<duration> XBRL-JSON format

I am storing XBRL JSON using elasticsearch.
This xBRL-JSON OIM spec describes the oim:period property:
Otherwise, an ISO 8601 time interval representing the {interval}
property, expressed in one of the following forms:
<start>/<end>
<start>/<duration>
<duration>/<end>
Where <start> and <end> are valid according to the xsd:dateTime datatype, and <duration> is valid according to xsd:duration.
Examples from arelle's plugin look like this:
2016-01-01T00:00:00/PT0S
2015-01-01T00:00:00/P1Y
I notice that arelle's plugin exclusively produces this format:
<start>/<duration>
My question
Is there a way to save at least the <start> part as a date type in elasticsearch?
Ideas I had:
elastichsearch only (my preference)
Use a custom date format which anticipates the /<duration> part, but ignores it
I haven't checked Joda yet; will it ignore characters in the date format if they aren't part of the special character? Like the "/" delimiter or the "P" which precedes any duration value (like PT0S and P1Y above)?
EDIT So the single-quote character escapes literals; this works yyyy'/P' will accept a value '2015/P'. However, the rest of the duration could be more dynamic
Re: dynamic; will Joda accept regex or wildcard character like "\d" or "+" qualifier so I can ignore all the possible variations following the P?
Use a character filter to strip out the /<duration> part before saving only <start>as datetime. But I don't know if character filters happen before saving as type: date. If they don't, the '/`part isn't stripped, and I wouldn't be passing valid date strings.
Don't use date type: Use a pattern tokenizer to split on /, and at least the two parts will be saved as separate tokens. Can't use date math, though.
Use a transformation; although it seems like this is deprecated. I read about using copy_to instead, but that seems to combine terms, and I want to break this term apart
Some sort of plugin? Maybe a plugin which will fully support this "interval" datatype described by the OIM spec... maybe a plugin which will store its separate parts...?
change my application (I prefer to use elasticsearch-only techniques if possible)
I could edit this plugin or produce my own plugin which uses exclusively <start> and <end> parts, and saves both into separate fields;
But this breaks the OIM spec, which says they should be combined in a single field
Moreover it can be awkward to express an "instant" fact (with no duration; the PT0S examples above); I guess I just use the same value for end property as start property... Not more awkward than a 0-length duration (PT0S) I guess.
Not a direct answer, but it's worth noting that the latest internal drafts of the xBRL-JSON specification have moved away from the the single-field representation. Although the "/" separated notation is an ISO standard, tool support for it appears to be extremely poor, and so the working group has chosen to switch to separate fields for start and end dates. I would expect Arelle support to follow suit in due course.

moment.js from now is reporting different results in firefox/ie then chrome

We and foolishly assumed a block of momentjs code would work in all browsers. Right now its correctly working in chrome, but all other browsers its not applying the UTC offset. How do I make this code work consistently in other browsers? Right now chrome is working, all others are not.
new moment(new Date(date)).fromNow();
//below shows an example of an exact date.
var now = new moment(new Date("2013-09-30T23:33:36.937")).fromNow();
In chrome you would see something like "now", all other browsers you would see "in 4 hours"
The way to get it to work:
var now = moment.utc("2013-10-01T13:15:30.937").fromNow();
Note that if you turn it into a "Date" and call moment.utc
var now = moment.utc(new Date("2013-10-01T13:15:30.937")).fromNow();
It will not work. It makes sense now that I think of it.
Original Answer
Try this:
var now = moment(date).fromNow();
But rutter is correct that you should specify either a Z or an offset like -07:00. From .net, you should make sure you use either a DateTime with .Kind set to Utc, or use a DateTimeOffset field.
Expanded Answer
You should understand that when you send a string of 2013-10-01T13:15:30.937, you are not sending any context with it. There is no way to know from that string alone whether the time is at UTC, or in your server's time zone, or in the browser's time zone.
If you pass it directly to moment("2013-10-01T13:15:30.937"), it is going to assume the context of the browser's local time zone.
As you discovered, you can tell moment explicitly that this time is in UTC by using the .utc function, such as moment.utc("2013-10-01T13:15:30.937").
While this will work, there are good reasons not to rely on that alone. For example, what if you ever use the same server API for another application, or perhaps for third-parties to consume? Unless you tell them separately that the timestamp is meant to represent UTC, then there is no way to know that.
These strings are in the ISO 8601 / RFC 3339 format. Part of that specification describes how to indicate that a timestamp is in UTC. You simply add a Z at the end. If you supply the Z then any consumer of this timestamp will know that the time should be interpreted as UTC. And sure enough, if you pass that into moment directly, such as moment("2013-10-01T13:15:30.937Z"), it will give the result you expected.
You said in comments that you were generating these values from ASP.Net Web API. Run your application in debug mode and set a breakpoint so you can examine the output of your controller. When you look at the specific DateTime property in question, you will see that it has its own .Kind property. It is probably set to DateTimeKind.Unspecified.
Since you said specifically that your application uses UTC, then these values should have DateTimeKind.Utc instead. Once that is set, then WebAPI will properly emit the Z at the end of the timestamp.
Somewhere in your server-side code, you should do something like this:
dt = DateTime.SpecifyKind(dt, DateTimeKind.Utc);
You should do this as early as possible. For example, in your data access layer when you retrieve the value from the database. If that's not possible, then at least you should do it in your API Controller so the value gets emitted properly.
See also the MSDN reference for DateTimeKind and DateTime.SpecifyKind.
Also - the reason you were getting browser inconsistencies is because you were using the Date object's constructor instead of the parsing functions built in to moment. While moment will accept a Date, there are several known problems and inconsistencies with how browsers support parsing a Date from a string. Some of those inconsistencies are documented here.
Use this:
var lastLoginTime = moment(user.lastLoginTime).fromNow();

How to show a UTC time as local time in a webpage?

I have a database that holds a time as UTC. This time can be shown in a webpage, so I’ve been asked to show it as local time in the page as it can be viewed from any country. A colleague mentioned something about getting the country settings from the current thread (on the server) but I couldn’t find any details on this. Is what I want to do possible?
If you (and your website) are comfortable with javascript, there is a very easy way to accomplish this.
First, on the server side, you would have the UTC date/time formatted in RFC 3339 format (the standard for internet time used by, among other protocols, icalendar). The basic syntax of RFC 3339 is:
YYYY-MM-DDTHH:MM:SS
Such that where I am, the time would be:
2010-05-04T05:52:33
But when the time is not local, but UTC, you add a Z to the end to denote this. So in my case, since I'm at -0500 hours from GMT, the same time above would be:
2010-05-04T10:52:33Z
So, first you get the server to output the above to your web page's javascript. The javascript can then parse that timestamp and it will output the date and time adjusted to the browser's time zone (which is determined by the computer hosting the browser). You should remember that if a user is from Tokyo and is viewing your website in Spain, they will see the timestamp in Tokyo time unless they've adjusted their computer's clock.
So the javascript would be:
var time_string_utc = some_server_variable; // timestamp from server
var time_string_utc_epoch = Date.parse(time_string_utc);
var time_utc = new Date();
time_utc.setTime(time_string_utc_epoch);
At this point, you have a javascript date object set to your UTC timestamp. A quick explanation of what happens above:
The first variable assumes you have passed the timestamp string to that variable from the server.
The second variable uses the Date.parse() method to convert the string to an epoch timestamp.
The third variable creates the unset Date object.
The last line line uses setTime method, which sets a Date object from an epoch timestamp.
Now that you have the object, you can output it to the user as you see fit. As a simple experiment, you can use:
document.write(time_utc);
which, if you are in my timezone using the UTC timestamp I started off with:
2010-05-04T10:52:33Z
would give:
Tue May 04 2010 05:52:33 GMT-0500 (CST)
but you can use various javascript methods to format the time into something much more pleasant looking.
No need to guess the user's country or even adjust your timestamp, so long as you trust the user's local browser/computer time zone.
Again, the short version:
var time_string_utc = some_server_variable; // UTC time from server
var time_string_utc_epoch = Date.parse(some_server_variable);
var time_utc = new Date();
time_utc.setTime(time_string_utc_epoch);
document.write(time_utc);
Also consider reading this thread which dives deeper in the dos and donts of handling daylight saving problem across timezones
Of-course is possible. You just need to find that country settings to detect the country your user comes from, and then modify the displayed date to fit that country's time.You can also find another way to detect the user country.(maybe from his ip address).
I am sure that the best way to manage this is let your colleague know that you need more details about the country settings implementation on your project and how can you use it.
EDIT:
Thinking about it I don't think it is possible to display the local time once you have the client’s culture. I'd certainly be interested to see your colleagues suggestion.
Getting the US culture, for example, won't help as the US has many timezones.
I think using Javascript like Anthony suggests would be the way to go...
OLD:
You can override the InitializeCulture() method with code that sets the current (chosen or browser reporting) cultures:
Thread.CurrentThread.CurrentCulture =
CultureInfo.CreateSpecificCulture(selectedLanguage);
Thread.CurrentThread.CurrentUICulture = new
CultureInfo(selectedLanguage);
this is how I've done it in PHP in the login file which connects to MySQL database:
//set local timezone
date_default_timezone_set('America/Denver'); //use local TZ
Then, every time you access the DB, you are setting the timezone for that session and any input/output associated with it.

Resources