-
Notifications
You must be signed in to change notification settings - Fork 22
/
Date.IntervalFromText.pq
124 lines (118 loc) · 3.76 KB
/
Date.IntervalFromText.pq
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/**
Given a string of text such as "Jan 2017 - Dec 2017" return a list of two
dates corresponding to beginning and end of the interval.
**/
(date_interval as text,
optional delimiter as text,
optional full_months as logical) =>
let
Date.Parse = try LibPQ("Date.Parse") otherwise Date.FromText,
/* Predefined intervals */
Presets = #table(
{"interval", "start", "end"},
{
{"1 квартал", "январь", "март"},
{"2 квартал", "апрель", "июнь"},
{"3 квартал", "июль", "сентябрь"},
{"4 квартал", "октябрь", "декабрь"},
{"1 полугодие", "январь", "июнь"},
{"2 полугодие", "июль", "декабрь"},
{"9 месяцев", "январь", "сентябрь"}
}
),
PresetFullYear = [
trim = {",","."," ",";"},
remove = {"г", "год"}
],
/* Default parameter values */
Delimiter = if delimiter is null then " - " else delimiter,
FullMonth = if
full_months is null
then
if
EndStrings{1} is null
then
Date.Day(DateStart) = 1
else
Date.Day(DateEndParsed) = 1 and Date.Day(DateStart) = 1
else
full_months,
/* Check if date_interval represents full year */
YearCandidates =
List.Transform(
PresetFullYear[remove],
each
try
Number.FromText(
Text.Trim(
Text.Replace(Text.Lower(date_interval), _, ""),
PresetFullYear[trim]
)
)
otherwise
null
),
YearDetected = List.Select(YearCandidates, each _ <> null){0},
YearText =
try
Text.From(#date(YearDetected, 1, 1)) &
Delimiter &
Text.From(#date(YearDetected, 12, 31))
otherwise
null,
/* Apply substitution presets if necessary */
SelectedPreset =
try
Table.ToRecords(
Table.SelectRows(
Table.AddColumn(
Presets,
"match",
each Text.Contains(
Text.Lower(date_interval),
[interval]
)
),
each [match] = true
)
){0}
otherwise
null,
ApplyPreset = (interval as text, preset as record) =>
let
input = Text.Lower(interval),
start = Text.Replace(input, preset[interval], preset[start]),
end = Text.Replace(input, preset[interval], preset[end])
in
start & Delimiter & end,
InputWithPresetsApplied =
if
SelectedPreset is null
then
date_interval
else
ApplyPreset(date_interval, SelectedPreset),
/* Parsing */
EndStrings = List.Combine({
Text.Split(
if
YearText is null
then
InputWithPresetsApplied
else
YearText,
Delimiter),
{null}
}),
DateStart = Date.Parse(EndStrings{0}),
DateEndParsed = try Date.Parse(EndStrings{1}) otherwise null,
DateEndGuess =
if
EndStrings{1} is null
then
DateStart
else
DateEndParsed,
DateEnd = if FullMonth then Date.EndOfMonth(DateEndGuess) else DateEndGuess
in
{DateStart, DateEnd}