@@ -2,6 +2,76 @@ import Benchmark
2
2
import Foundation
3
3
import Parsing
4
4
5
+ #if swift(>=5.8)
6
+ struct DateTime : Parser {
7
+ var body : some Parser < Substring . UTF8View , Date > {
8
+ Parse ( Date . init ( year: month: day: hour: minute: second: nanosecond: timeZone: ) ) {
9
+ Digits ( 4 )
10
+ " - " . utf8
11
+ Digits ( 2 ) . filter { ( 1 ... 12 ) . contains ( $0) }
12
+ " - " . utf8
13
+ Digits ( 2 ) . filter { ( 1 ... 31 ) . contains ( $0) }
14
+ " T " . utf8
15
+ Digits ( 2 ) . filter { $0 < 24 }
16
+ " : " . utf8
17
+ Digits ( 2 ) . filter { $0 < 60 }
18
+ " : " . utf8
19
+ Digits ( 2 ) . filter { $0 <= 60 }
20
+ Parse {
21
+ " . " . utf8
22
+ Prefix ( 1 ... 9 , while: ( UInt8 ( ascii: " 0 " ) ... UInt8 ( ascii: " 9 " ) ) . contains)
23
+ . compactMap { n in Int ( Substring ( n) ) . map { $0 * Int( pow ( 10 , 9 - Double( n. count) ) ) } }
24
+ }
25
+ . replaceError ( with: 0 )
26
+ OneOf {
27
+ " Z " . utf8. map { 0 }
28
+ Parse {
29
+ OneOf {
30
+ " + " . utf8. map { 1 }
31
+ " - " . utf8. map { - 1 }
32
+ }
33
+ Digits ( 2 ) . filter { $0 < 24 } . map { $0 * 60 * 60 }
34
+ " : " . utf8
35
+ Digits ( 2 ) . filter { $0 < 60 } . map { $0 * 60 }
36
+ }
37
+ . map { $0 * ( $1 + $2) }
38
+ }
39
+ }
40
+ }
41
+ }
42
+
43
+ private extension Date {
44
+ init (
45
+ year: Int ,
46
+ month: Int ,
47
+ day: Int ,
48
+ hour: Int ,
49
+ minute: Int ,
50
+ second: Int ,
51
+ nanosecond: Int ,
52
+ timeZone: Int
53
+ ) {
54
+ var components = tm (
55
+ tm_sec: Int32 ( second) ,
56
+ tm_min: Int32 ( minute) ,
57
+ tm_hour: Int32 ( hour) ,
58
+ tm_mday: Int32 ( day) ,
59
+ tm_mon: Int32 ( month - 1 ) ,
60
+ tm_year: Int32 ( year - 1900 ) ,
61
+ tm_wday: 0 ,
62
+ tm_yday: 0 ,
63
+ tm_isdst: 0 ,
64
+ tm_gmtoff: 0 ,
65
+ tm_zone: nil
66
+ )
67
+ let time = timegm ( & components)
68
+ var timeIntervalSince1970 = TimeInterval ( time - timeZone)
69
+ timeIntervalSince1970 += TimeInterval ( nanosecond) / 1_000_000_000
70
+ self . init ( timeIntervalSince1970: timeIntervalSince1970)
71
+ }
72
+ }
73
+ #endif
74
+
5
75
/// This benchmarks implements an [RFC-3339-compliant](https://www.ietf.org/rfc/rfc3339.txt) date
6
76
/// parser in a relatively naive way and pits it against `DateFormatter` and `ISO8601DateFormatter`.
7
77
///
@@ -10,62 +80,12 @@ import Parsing
10
80
/// nanosecond, while the formatters do not parse beyond the millisecond.
11
81
let dateSuite = BenchmarkSuite ( name: " Date " ) { suite in
12
82
#if swift(>=5.8)
13
- struct DateTime : Parser {
14
- var body : some Parser < Substring . UTF8View , DateComponents > {
15
- Parse { year, month, day, hour, minute, second, nanosecond, timeZone in
16
- DateComponents (
17
- timeZone: timeZone,
18
- year: year,
19
- month: month,
20
- day: day,
21
- hour: hour,
22
- minute: minute,
23
- second: second,
24
- nanosecond: nanosecond
25
- )
26
- } with: {
27
- Digits ( 4 )
28
- " - " . utf8
29
- Digits ( 2 )
30
- " - " . utf8
31
- Digits ( 2 )
32
- " T " . utf8
33
- Digits ( 2 )
34
- " : " . utf8
35
- Digits ( 2 )
36
- " : " . utf8
37
- Digits ( 2 )
38
- Optionally {
39
- " . " . utf8
40
- Prefix ( 1 ... 9 , while: ( UInt8 ( ascii: " 0 " ) ... UInt8 ( ascii: " 9 " ) ) . contains)
41
- . compactMap { n in Int ( Substring ( n) ) . map { $0 * Int( pow ( 10 , 9 - Double( n. count) ) ) } }
42
- }
43
- OneOf {
44
- " Z " . utf8. map { 0 }
45
- Parse {
46
- OneOf {
47
- " + " . utf8. map { 1 }
48
- " - " . utf8. map { - 1 }
49
- }
50
- Digits ( 2 ) . map { $0 * 60 * 60 }
51
- " : " . utf8
52
- Digits ( 2 ) . map { $0 * 60 }
53
- }
54
- . map { $0 * ( $1 + $2) }
55
- }
56
- . map { TimeZone ( secondsFromGMT: $0) }
57
- }
58
- }
59
- }
60
-
61
83
let input = " 1979-05-27T00:32:00Z "
62
84
let expected = Date ( timeIntervalSince1970: 296_613_120 )
63
85
var output : Date !
64
86
65
- let dateTimeParser = DateTime ( ) . compactMap ( Calendar . current. date ( from: ) )
66
87
suite. benchmark ( " Parser " ) {
67
- var input = input [ ... ] . utf8
68
- output = try dateTimeParser. parse ( & input)
88
+ output = try DateTime ( ) . parse ( input)
69
89
} tearDown: {
70
90
precondition ( output == expected)
71
91
}
0 commit comments