Skip to content

Commit e26d39b

Browse files
committed
Merge pull request #8125 from JuliaLang/jq/dates
Add day of week formatting ability
2 parents cde0204 + 9f13004 commit e26d39b

File tree

3 files changed

+49
-14
lines changed

3 files changed

+49
-14
lines changed

base/dates/io.jl

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -56,24 +56,28 @@ immutable DateFormat
5656
trans #trans[i] == how to transition FROM slots[i] TO slots[i+1]
5757
end
5858

59+
immutable DayOfWeekSlot <: AbstractTime end
60+
5961
duplicates(slots) = any(map(x->count(y->x.period==y.period,slots),slots) .> 1)
6062

6163
function DateFormat(f::String,locale::String="english")
6264
slots = Slot[]
6365
trans = {}
64-
begtran = match(r"^.*?(?=[ymuUdHMSs])",f).match
65-
ss = split(f,r"^.*?(?=[ymuUdHMSs])")
66-
s = split(begtran == "" ? ss[1] : ss[2],r"[^ymuUdHMSs]|(?<=([ymuUdHMSs])(?!\1))")
66+
begtran = match(r"^.*?(?=[ymuUdHMSsEe])",f).match
67+
ss = split(f,r"^.*?(?=[ymuUdHMSsEe])")
68+
s = split(begtran == "" ? ss[1] : ss[2],r"[^ymuUdHMSsEe]+|(?<=([ymuUdHMSsEe])(?!\1))")
6769
for (i,k) in enumerate(s)
6870
k == "" && break
6971
tran = i >= endof(s) ? r"$" : match(Regex("(?<=$(s[i])).*(?=$(s[i+1]))"),f).match
7072
slot = tran == "" || tran == r"$" ? FixedWidthSlot : DelimitedSlot
7173
width = length(k)
72-
typ = 'y' in k ? Year : 'm' in k ? Month :
74+
typ = 'E' in k ? DayOfWeekSlot : 'e' in k ? DayOfWeekSlot :
75+
'y' in k ? Year : 'm' in k ? Month :
7376
'u' in k ? Month : 'U' in k ? Month :
7477
'd' in k ? Day : 'H' in k ? Hour :
7578
'M' in k ? Minute : 'S' in k ? Second : Millisecond
76-
option = 'U' in k ? 2 : 'u' in k ? 1 : 0
79+
option = 'E' in k ? 2 : 'e' in k ? 1 :
80+
'U' in k ? 2 : 'u' in k ? 1 : 0
7781
push!(slots,slot(i,typ,width,option,locale))
7882
push!(trans,tran)
7983
end
@@ -82,18 +86,18 @@ function DateFormat(f::String,locale::String="english")
8286
end
8387

8488
const SLOTERROR = ArgumentError("Non-digit character encountered")
85-
slotparse(slot,x) = !ismatch(r"\D",x) ? slot.period(x) : throw(SLOTERROR)
89+
slotparse(slot,x) = !ismatch(r"[^0-9\s]",x) ? slot.period(x) : throw(SLOTERROR)
8690
function slotparse(slot::Slot{Month},x)
8791
if slot.option == 0
88-
ismatch(r"\D",x) && throw(SLOTERROR)
89-
return Month(x)
92+
ismatch(r"[^0-9\s]",x) ? throw(SLOTERROR) : return Month(x)
9093
elseif slot.option == 1
9194
return Month(MONTHTOVALUEABBR[slot.locale][lowercase(x)])
9295
else
9396
return Month(MONTHTOVALUE[slot.locale][lowercase(x)])
9497
end
9598
end
96-
slotparse(slot::Slot{Millisecond},x) = !ismatch(r"\D",x) ? slot.period(parsefloat("."*x)*1000.0) : throw(SLOTERROR)
99+
slotparse(slot::Slot{Millisecond},x) = !ismatch(r"[^0-9\s]",x) ? slot.period(parsefloat("."*x)*1000.0) : throw(SLOTERROR)
100+
slotparse(slot::Slot{DayOfWeekSlot},x) = nothing
97101

98102
function getslot(x,slot::DelimitedSlot,df,cursor)
99103
endind = first(search(x,df.trans[slot.i],cursor+1))
@@ -108,13 +112,13 @@ getslot(x,slot,df,cursor) = (cursor+slot.width, slotparse(slot,x[cursor:(cursor+
108112
function parse(x::String,df::DateFormat)
109113
x = strip(replace(x, r"#.*$", ""))
110114
x = replace(x,df.begtran,"")
111-
isempty(x) && throw(ArgumentError("Cannot parse empty string"))
115+
isempty(x) && throw(ArgumentError("Cannot parse empty format string"))
112116
(typeof(df.slots[1]) <: DelimitedSlot && first(search(x,df.trans[1])) == 0) && throw(ArgumentError("Delimiter mismatch. Couldn't find first delimiter, \"$(df.trans[1])\", in date string"))
113117
periods = Period[]
114118
cursor = 1
115119
for slot in df.slots
116120
cursor, pe = getslot(x,slot,df,cursor)
117-
push!(periods,pe)
121+
pe != nothing && push!(periods,pe)
118122
cursor > endof(x) && break
119123
end
120124
return sort!(periods,rev=true,lt=periodisless)
@@ -131,6 +135,13 @@ function slotformat(slot::Slot{Month},dt)
131135
return VALUETOMONTH[slot.locale][month(dt)]
132136
end
133137
end
138+
function slotformat(slot::Slot{DayOfWeekSlot},dt)
139+
if slot.option == 1
140+
return VALUETODAYOFWEEKABBR[slot.locale][dayofweek(dt)]
141+
else # == 2
142+
return VALUETODAYOFWEEK[slot.locale][dayofweek(dt)]
143+
end
144+
end
134145
slotformat(slot::Slot{Millisecond},dt) = rpad(string(millisecond(dt)/1000.0)[3:end], slot.width, "0")
135146

136147
function format(dt::TimeType,df::DateFormat)
@@ -145,6 +156,7 @@ end
145156
# UI
146157
const ISODateTimeFormat = DateFormat("yyyy-mm-ddTHH:MM:SS.s")
147158
const ISODateFormat = DateFormat("yyyy-mm-dd")
159+
const RFC1123Format = DateFormat("e, dd u yyyy HH:MM:SS")
148160

149161
DateTime(dt::String,format::String;locale::String="english") = DateTime(dt,DateFormat(format,locale))
150162
DateTime(dt::String,df::DateFormat=ISODateTimeFormat) = DateTime(parse(dt,df)...)

test/dates/io.jl

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,4 +274,27 @@ t = Dates.DateTime(1,1,1,14,51,0,118)
274274
@test Dates.DateTime("[14:51:00.118?", "[HH:MM:SS.sss?") == t
275275
@test Dates.DateTime("?14:51:00.118?", "?HH:MM:SS.sss?") == t
276276
@test Dates.DateTime("x14:51:00.118", "xHH:MM:SS.sss") == t
277-
@test Dates.DateTime("14:51:00.118]", "HH:MM:SS.sss]") == t
277+
@test Dates.DateTime("14:51:00.118]", "HH:MM:SS.sss]") == t
278+
279+
# RFC1123Format
280+
dt = Dates.DateTime(2014,8,23,17,22,15)
281+
@test Dates.format(dt,Dates.RFC1123Format) == "Sat, 23 Aug 2014 17:22:15"
282+
@test Dates.DateTime(Dates.format(dt,Dates.RFC1123Format),Dates.RFC1123Format) == dt
283+
@test Dates.format(dt,"yyyy-mm-ddTHH:MM:SS E") == "2014-08-23T17:22:15 Saturday"
284+
@test Dates.format(dt,"yyyy-mm-ddTHH:MM:SS e") == "2014-08-23T17:22:15 Sat"
285+
@test Dates.format(dt,"yyyy-mm-dd E") == "2014-08-23 Saturday"
286+
@test Dates.format(dt,"yyyy-mm-dd e") == "2014-08-23 Sat"
287+
@test Dates.format(dt,"yyyy-e-mm-dd") == "2014-Sat-08-23"
288+
289+
@test Dates.format(Dates.DateTime(2014,1,2,0,0,0,999),Dates.RFC1123Format) == "Thu, 02 Jan 2014 00:00:00"
290+
@test Dates.format(Dates.DateTime(2014,2,18,0,0,0,9),Dates.RFC1123Format) == "Tue, 18 Feb 2014 00:00:00"
291+
@test Dates.format(Dates.DateTime(2014,3,8,0,0,0,9),Dates.RFC1123Format) == "Sat, 08 Mar 2014 00:00:00"
292+
@test Dates.format(Dates.DateTime(2014,4,28,0,0,0,9),Dates.RFC1123Format) == "Mon, 28 Apr 2014 00:00:00"
293+
@test Dates.format(Dates.DateTime(2014,5,10,0,0,0,9),Dates.RFC1123Format) == "Sat, 10 May 2014 00:00:00"
294+
@test Dates.format(Dates.DateTime(2014,6,4,0,0,0,9),Dates.RFC1123Format) == "Wed, 04 Jun 2014 00:00:00"
295+
@test Dates.format(Dates.DateTime(2014,7,13,0,0,0,9),Dates.RFC1123Format) == "Sun, 13 Jul 2014 00:00:00"
296+
@test Dates.format(Dates.DateTime(2014,8,17,0,0,0,9),Dates.RFC1123Format) == "Sun, 17 Aug 2014 00:00:00"
297+
@test Dates.format(Dates.DateTime(2014,9,20,0,0,0,9),Dates.RFC1123Format) == "Sat, 20 Sep 2014 00:00:00"
298+
@test Dates.format(Dates.DateTime(2014,10,31,0,0,0,9),Dates.RFC1123Format) == "Fri, 31 Oct 2014 00:00:00"
299+
@test Dates.format(Dates.DateTime(2014,11,2,0,0,0,9),Dates.RFC1123Format) == "Sun, 02 Nov 2014 00:00:00"
300+
@test Dates.format(Dates.DateTime(2014,12,5,0,0,0,9),Dates.RFC1123Format) == "Fri, 05 Dec 2014 00:00:00"

test/dates/periods.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ y2 = Dates.Year(2)
124124
@test_throws ArgumentError Dates.Year(mi) == y
125125
@test_throws ArgumentError Dates.Year(s) == y
126126
@test_throws ArgumentError Dates.Year(ms) == y
127-
@test Dates.Year(Date(2013,1,1)) == Dates.Year(2013)
128-
@test Dates.Year(DateTime(2013,1,1)) == Dates.Year(2013)
127+
@test Dates.Year(Dates.Date(2013,1,1)) == Dates.Year(2013)
128+
@test Dates.Year(Dates.DateTime(2013,1,1)) == Dates.Year(2013)
129129
@test typeof(y+m) <: Dates.CompoundPeriod
130130
@test typeof(m+y) <: Dates.CompoundPeriod
131131
@test typeof(y+w) <: Dates.CompoundPeriod

0 commit comments

Comments
 (0)