Fable
Fable copied to clipboard
DateTime.ParseExact breaks REPL
open System
open System.Globalization
let date = DateTime.ParseExact("21.10.2020", "dd.MM.yyyy", CultureInfo.InvariantCulture)
printfn "Date %O" date
DateTime.ParseExact is not implemented at the moment.
We should add a compiler error for it, or it should be implemented.
Typically my need for using DateTime.PaseExact is because I want to parse a string to a date using some specific date format, and I am guessing the same is true for most other people.
Presently, I want to parse a string in "dd/MM/yyyy" format, on the client side.
I am hoping this can be done using DateTime.TryParse and providing a custom implementation of IFormatProvider.
However, the example I linked to is (to me anyway) a mess of OOP inheritance and stuff which I can't currently understand.
The interface defines as single method called GetFormat(type) but I can't figure out if the type I need to cater for is DateTime or (as in the example) ICustomFormatter.
Anyway, I think an example of how to do this (if indeed it is possible) would be a good thing for the documentation so that it becomes a widely known work around. Anyone know how to do this?
@travis-leith The Elmish Book has a section on Parsing Date Segments where if you ignore the parts related to the router, you can parse like this
[<RequireQualifiesAccess>]
module Date
open System
let (|Between|_|) (x: int) (y: int) (input: int) =
if input >= x && input <= y
then Some()
else None
let isLeapYear (year: int) = DateTime.IsLeapYear(year)
type DateParts = { day: int; month: int; year: int }
let buildDate (parts: DateParts) : Option<DateTime> =
let day, month, year = parts.day, parts.month, parts.year
if year <= 0 then
None
else
match month, day with
| 2, Between 1 29 when isLeapYear year -> Some (DateTime(year, month, day))
| 2, Between 1 28 when not (isLeapYear year) -> Some (DateTime(year, month, day))
| (1 | 3 | 5 | 7 | 8 | 10 | 12), Between 1 31 -> Some (DateTime(year, month, day))
| (4 | 6 | 9 | 11), Between 1 30 -> Some (DateTime(year, month, day))
| _ -> None
let (|Int|_|) (number: string) =
match Int32.TryParse number with
| (true, value) -> Some value
| _ -> None
let parse (date: string) : Option<DateTime> =
match date.Split '/' with
| [| Int day; Int month; Int year |] -> buildDate { day = day; month = month; year = year }
| _ -> None
Then you can the module like this
match Date.parse inputDate with
| Some parsedDate -> (* do stuff *)
| None -> (* invalid *)
Notice the function parse will split the input date string on / but you can change that to whatever you like and in read the parts in the order you want
@Zaid-Ajaj this works well, thank you.