如果我从命令行获取一个字符串,它看起来像这样:
'1-1-2011'
Run Code Online (Sandbox Code Playgroud)
如何将该字符串转换为F#中的DateTime对象?
Ste*_*sen 22
根据您的具体需要,.NET的日期时间类有字符串转换为一些静态方法DateTime的情况下,这些都是DateTime.Parse,DateTime.ParseExact和DateTime.TryParse他们几个重载.
@ 7sharp9演示了执行日期解析的最基本方法,直接调用方法DateTime.Parse.但是,F#中的事情变得有趣DateTime.TryParse.而DateTime.Parse如果解析失败会抛出异常,最简单的过载DateTime.TryParse有签名string * byref<DateTime> -> bool,这将返回解析是否成功设置byref,如果真参数解析日期,或将它的默认值(null在这种情况下),否则.但是,在F#中使用它的语法很麻烦(事实上它并不适合任何.NET语言),因此F#语言设计了一个特殊的功能,允许像@Thomas Petricek指出的那样更好的调用约定.出.
但即使是F#(bool,result)返回类型模式也不理想.大多数情况下,如果解析失败,则不需要默认值.一个更好的签名DateTime.TryParse将是string -> option<DateTime>.幸运的是,我们可以随意扩展DateTime:
type System.DateTime with
static member TryParseOption str =
match DateTime.TryParse str with
| true, r -> Some(r)
| _ -> None
Run Code Online (Sandbox Code Playgroud)
我们使用上面的扩展名如下:
match System.DateTime.TryParseOption "11/11/11" with
| Some r -> stdout.WriteLine r
| None -> stdout.WriteLine "none"
Run Code Online (Sandbox Code Playgroud)
这与F#约定更为一致(List.tryFind例如).但即使这样也可以"变得更好".注意我们如何匹配try解析的结果.使用部分活动模式(当然!),我们可以包装整个类的try parses并将匹配移动到匹配大小写以获得更大的灵活性.请采取以下措施
open System
let (|DateTime|_|) str =
match DateTime.TryParse str with
| true, dt -> Some(dt)
| _ -> None
let (|Int|_|) str =
match Int32.TryParse str with
| true, num -> Some(num)
| _ -> None
let (|Float|_|) str =
match Double.TryParse str with
| true, num -> Some(num)
| _ -> None
Run Code Online (Sandbox Code Playgroud)
使用这些,我们可以编写一个简洁的小控制台应用程序:
let rec loop() =
stdout.WriteLine "
Please select an option:
1) Parse something
2) Exit
"
match stdin.ReadLine() with
| Int 1 ->
stdout.WriteLine "Enter something to parse: "
match stdin.ReadLine() with
| Int num -> stdout.WriteLine("Successfully parsed int: {0}", num)
| Float num -> stdout.WriteLine("Successfully parsed float: {0}", num)
| DateTime dt -> stdout.WriteLine("Successfully parsed DateTime: {0}", dt)
| _ -> stdout.WriteLine "Parse Failed!"
loop()
| Int 2 ->
stdout.WriteLine "Now exiting"
| _ ->
stdout.WriteLine "Invalid option, please try again"
loop()
Run Code Online (Sandbox Code Playgroud)
要注意的关键是嵌套的匹配项,其中Int,Float,DateTime执行同样的匹配表达式内的尝试解析.
这些活动模式还有其他简洁的应用,例如,我们可以简洁地同时过滤和映射日期字符串列表
> ["11/23/2003"; "not a date"; "1/1/23 23:23pm"] |> Seq.choose(|DateTime|_|);;
val it : seq<DateTime> =
seq
[11/23/2003 12:00:00 AM {Date = 11/23/2003 12:00:00 AM;
Day = 23;
DayOfWeek = Sunday;
DayOfYear = 327;
Hour = 0;
Kind = Unspecified;
Millisecond = 0;
Minute = 0;
Month = 11;
Second = 0;
Ticks = 632051424000000000L;
TimeOfDay = 00:00:00;
Year = 2003;};
1/1/2023 11:23:00 PM {Date = 1/1/2023 12:00:00 AM;
Day = 1;
DayOfWeek = Sunday;
DayOfYear = 1;
Hour = 23;
Kind = Unspecified;
Millisecond = 0;
Minute = 23;
Month = 1;
Second = 0;
Ticks = 638082121800000000L;
TimeOfDay = 23:23:00;
Year = 2023;}]
Run Code Online (Sandbox Code Playgroud)
7sh*_*rp9 11
你可以像这样简单地做到:
let dateTime = System.DateTime.Parse "1-1-2011"
Run Code Online (Sandbox Code Playgroud)
Tom*_*cek 11
要为7sharp9写的内容添加一个好东西,如果你还想处理失败,你可以写:
match System.DateTime.TryParse "1-1-2011" with
| true, date -> printfn "Success: %A" date
| false, _ -> printfn "Failed!"
Run Code Online (Sandbox Code Playgroud)
这并不明显,因为该TryParse方法有一个byref<DateTime>作为最后一个参数(并且它out在C#中使用),但F#允许您像这样调用方法.
| 归档时间: |
|
| 查看次数: |
9153 次 |
| 最近记录: |