working with dates with F# - f#

I am really newbie in F#. Below is my attempt in creating a function that calculates the difference between two dates.
let test date =
let today = DateTime.Now
let fromdate = DateTime.Parse(date)
let count = Convert.ToInt32(today - fromdate)
date
The above code prompts the error
System.InvalidCastException: Unable to cast object of type
'System.TimeSpan' to type 'System.IConvertible'.

You don't need to convert the time span resulting from applying the "minus" operator to two dates.
The screenshot below is my attempt at fixing your function and an example of value it returns.

The difference between two DateTimes will give you a TimeSpan object, on which you can further operate. This should be the last statement in your function, as it will be used as the return value. You can check the MS docs in the link for the various properties and methods. Strictly speaking, this is part of the BCL, so it's rather .NET than just F# (you would do the same in VB or C#). If you want to further refine your function you should examine DateTime.TryParse as well and handle the possibility of not receiving a valid date.
open System
let test date =
let today = DateTime.Now
let fromdate = DateTime.Parse(date)
(today - fromdate).Days
test "2017/12/31" // val it : int = -325

Related

conditional field in anonymous records, in f#

I often use anonmymous records to build on the go data that will eventually be serialized and returned to be consumed somewhere else. This is very flexible, quick to deal with, etc.
But one thing I'm really missing is the ability to do something like this pseudo code:
{|
SomeData = 3
StartTime = ....
if ProcessedFinished then yield { EndTime = ... }
|}
when I could add a field, or not, based on some conditions.
Is there a solution to have the flexibility of the anonymous record, yet have the ability to make conditions like this? I could do a dictionary, then insert values based on conditions but then I'd have to box all the values as well and it would be messy right away.
What you're after is not possible today, but you can get pretty close like so:
let initialData =
{|
SomeData = 3
StartTime = ....
|}
if ProcessedFinished then
{| initialData with EndTime = ... |}
else
initialData
Of course, to represent this as a return type it's now more involved, as you'll likely need to use SRTP in the signature to account for any type with a SomeData and StartTime member on it. It's perfectly fine if this is just in the body of a routine that then produces another result to return, though.
If you want to represent data that may be optionally available based on a condition, especially if you want it to live outside of a given function, I'd recommend an option for that field instead.

Not able to query documents by geohash in google firestore, using created date field?

I am using Google Firestore geoqueries Following this documentation. Querying documents within a distance using geohash works fine. When I introduce a new condition: `.whereField("createdOn", isGreaterThan: <value for time interval since 1970 7 days ago>)
This throws an error saying, any inequality on a field must have this field as the first 'OrderBy' parameter. When I add order by parameter for this field, it no longer returns the document that is still within the distance searched but shows no error.
Is it even possible to use the firestore geoqueries with additional query conditions?
I need to be able to limit the query by objects created within a certain timeframe, otherwise this will return a very large number of documents. Sorting these post-query will surely impact app performance. Maybe I am missing a more practical way of using geoqueries in Firestore?
let queryBounds = GFUtils.queryBounds(forLocation: center,
withRadius: distanceM)
//test
let ref = Ref().databaseJobs
let currentTime = NSDate().timeIntervalSince1970
let intervalLastWeek = currentTime - (10080 * 60)
print("current time is: \(currentTime) and 7 days ago interval was \(intervalLastWeek)")
ref.whereField("createdOn", isGreaterThan: intervalLastWeek)
let queries = queryBounds.compactMap { (any) -> Query? in
guard let bound = any as? GFGeoQueryBounds else { return nil }
return ref
.order(by: "geohash")
.start(at: [bound.startValue])
.end(at: [bound.endValue])
.whereField("createdOn", isGreaterThan: intervalLastWeek)
Firestore can only filter on range on a single field. Or simpler: you can only have a single orderBy clause in your query.
What you are trying to do requires two orderBy clauses, one for geohash and one for createdOn, which isn't possible. If you were to need an equality check on a second field though, that would be possible as thstt doesn't require an orderBy clause.
What I'm wondering is whether you can add a field createdOnDay that contains just the day part of createdOn in a fixed format, and then perform an in on that with 7 values (for the days of the past week?

Esper EPL Online Date format

I'm trying to use the Esper EPL Online console and I don't know how to use Dates in the Time And Event Sequence. For example, I have a schema defined like this:
create schema EventCreated(
source String,
type String,
time Date
);
And I'm trying to add an event in the Time And Event Sequence, for example like this:
EventCreated = {
source = 'tracker1',
type = 'c8y_ObdConnectionReport',
time = '2016-10-07T10:00:00.000'
}
But of course this doesn't work. I tried using "new Date()" or [com.espertech.esper.client.util.]DateTime.parseDefaultDate() but I can't make it work.
There is an "eval" for evaluating EPL expressions.
StockTick={time=eval('com.espertech.esper.client.util.DateTime.parseDefaultDate("2016-10-07T10:00:00.000")')}
It would be nice though if the tool would just take the string and make it a date.

Grab the highest date inside of an array of entities.

I have the following array :
let messages = (fetchedResultsController.fetchedObjects as! [Message])
essentially, each element in this array is of the entity Message, where each Message has 5 core data attributes. Notably, the attribute I care about in this case is timestamp which is of type NSDate !!!!!!. I want to grab the message with the maximum date inside of this array using the reduce function. Please do not suggest to sort the messages first. I'am trying to avoid that. Thank you !
Not sure why you would want to use reduce, but I think this will work and fits with what you are looking for (assuming Swift 3):
let result = messages.max(by: {$0.timeStamp < $1.timeStamp})

entity vs. dapper datetime check not worker

I have entity and also use dapper, I have 1 form with 2 date fields... named before and after so users can search in between those dates. The one from entity works perfectly but the one from dapper does not work for some reason what could possibly be wrong
here is the entity one
var article = (from x in db.Articles
where x.created >= before && x.created <= after
select x);
and here is the one from dapper
var article = sqlConnection.Query<Article>("Select * from articles where created>=#befor AND created<=#afte ", new { befor = before, afte = after});
and yes I have all the connections for Dapper working as it does go to the database but for some reason its not picking records between those 2 dates..any suggestions..
dapper is just a wrapper around raw TSQL (with a slight caveat around in, where dapper adds some magic to make varadic "in" queries simpler). So; if it works in TSQL it should work fine in dapper, as long as your inputs make sense. For example, I am assuming that before and after in this example are typed as non-nullable DateTime, i.e.
DateTime before = ..., after = ...;
var article = sqlConnection.Query<Article>(
"Select * from articles where created>=#befor AND created<=#afte ",
new { befor = before, afte = after});
as a side note, it would perhaps be more obvious to just use:
DateTime before = ..., after = ...;
var article = sqlConnection.Query<Article>(
"Select * from articles where created>=#before AND created<=#after",
new { before, after });
but fundamentally, as long as those parameters have non-null values that are DateTimes, it should work fine.
The problem here could be that the before and after values are send as string and the current locale may be causing the date to be interpreted incorrectly.

Resources