mirror of
https://github.com/araddon/dateparse.git
synced 2024-11-14 11:31:33 +08:00
Merge pull request #41 from araddon/issue_40
Fix a bad parse date, closes #40
This commit is contained in:
commit
d7f44806bc
114
parseany.go
114
parseany.go
@ -129,7 +129,7 @@ func parseTime(datestr string, loc *time.Location) (time.Time, error) {
|
|||||||
|
|
||||||
part1Len := 0
|
part1Len := 0
|
||||||
part2Len := 0
|
part2Len := 0
|
||||||
dayLen := 0
|
part3Len := 0
|
||||||
|
|
||||||
// General strategy is to read rune by rune through the date looking for
|
// General strategy is to read rune by rune through the date looking for
|
||||||
// certain hints of what type of date we are dealing with.
|
// certain hints of what type of date we are dealing with.
|
||||||
@ -162,6 +162,7 @@ iterRunes:
|
|||||||
switch r {
|
switch r {
|
||||||
case '-', '\u2212':
|
case '-', '\u2212':
|
||||||
state = stateDigitDash
|
state = stateDigitDash
|
||||||
|
part1Len = i
|
||||||
case '/':
|
case '/':
|
||||||
state = stateDigitSlash
|
state = stateDigitSlash
|
||||||
part1Len = i
|
part1Len = i
|
||||||
@ -174,22 +175,28 @@ iterRunes:
|
|||||||
}
|
}
|
||||||
|
|
||||||
case stateDigitDash: // starts digit then dash 02-
|
case stateDigitDash: // starts digit then dash 02-
|
||||||
|
// 2006-01-02
|
||||||
|
// stateDigitDashT
|
||||||
// 2006-01-02T15:04:05Z07:00
|
// 2006-01-02T15:04:05Z07:00
|
||||||
// 2017-06-25T17:46:57.45706582-07:00
|
// 2017-06-25T17:46:57.45706582-07:00
|
||||||
// 2006-01-02T15:04:05.999999999Z07:00
|
// 2006-01-02T15:04:05.999999999Z07:00
|
||||||
// 2006-01-02T15:04:05+0000
|
// 2006-01-02T15:04:05+0000
|
||||||
|
// stateDigitDashWs
|
||||||
// 2012-08-03 18:31:59.257000000
|
// 2012-08-03 18:31:59.257000000
|
||||||
// 2014-04-26 17:24:37.3186369
|
// 2014-04-26 17:24:37.3186369
|
||||||
// 2017-01-27 00:07:31.945167
|
// 2017-01-27 00:07:31.945167
|
||||||
// 2016-03-14 00:00:00.000
|
// 2016-03-14 00:00:00.000
|
||||||
// 2014-05-11 08:20:13,787
|
// 2014-05-11 08:20:13,787
|
||||||
// 2017-07-19 03:21:51+00:00
|
// 2017-07-19 03:21:51+00:00
|
||||||
// 2006-01-02
|
|
||||||
// 2013-04-01 22:43:22
|
// 2013-04-01 22:43:22
|
||||||
// 2014-04-26 05:24:37 PM
|
// 2014-04-26 05:24:37 PM
|
||||||
|
// stateDigitDashAlpha
|
||||||
// 2013-Feb-03
|
// 2013-Feb-03
|
||||||
switch {
|
switch {
|
||||||
|
case r == '-':
|
||||||
|
part2Len = i - part1Len - 1
|
||||||
case r == ' ':
|
case r == ' ':
|
||||||
|
part3Len = i - part1Len - part2Len - 1 - 1
|
||||||
state = stateDigitDashWs
|
state = stateDigitDashWs
|
||||||
case r == 'T':
|
case r == 'T':
|
||||||
state = stateDigitDashT
|
state = stateDigitDashT
|
||||||
@ -555,8 +562,8 @@ iterRunes:
|
|||||||
// stateWeekdayAbbrevCommaOffsetZone
|
// stateWeekdayAbbrevCommaOffsetZone
|
||||||
// Tue, 11 Jul 2017 16:28:13 +0200 (CEST)
|
// Tue, 11 Jul 2017 16:28:13 +0200 (CEST)
|
||||||
switch {
|
switch {
|
||||||
case r == ' ' && dayLen == 0:
|
case r == ' ' && part3Len == 0:
|
||||||
dayLen = i - part1Len - 2
|
part3Len = i - part1Len - 2
|
||||||
case r == '-':
|
case r == '-':
|
||||||
if i < 15 {
|
if i < 15 {
|
||||||
state = stateWeekdayAbbrevCommaDash
|
state = stateWeekdayAbbrevCommaDash
|
||||||
@ -915,19 +922,42 @@ iterRunes:
|
|||||||
|
|
||||||
case stateDigitDashWsWsOffsetColon:
|
case stateDigitDashWsWsOffsetColon:
|
||||||
// 2006-01-02 15:04:05 -07:00
|
// 2006-01-02 15:04:05 -07:00
|
||||||
|
switch {
|
||||||
|
case part2Len == 2 && part3Len == 2:
|
||||||
for _, layout := range []string{
|
for _, layout := range []string{
|
||||||
"2006-01-02 15:04:05 -07:00",
|
"2006-01-02 15:04:05 -07:00",
|
||||||
"2006-01-02 15:04:5 -07:00",
|
"2006-01-02 15:04:5 -07:00",
|
||||||
"2006-01-02 15:4:05 -07:00",
|
"2006-01-02 15:4:05 -07:00",
|
||||||
"2006-01-02 15:4:5 -07:00",
|
"2006-01-02 15:4:5 -07:00",
|
||||||
"2006-1-02 15:04:05 -07:00",
|
} {
|
||||||
"2006-1-02 15:4:05 -07:00",
|
if t, err := parse(layout, datestr, loc); err == nil {
|
||||||
"2006-1-02 15:04:5 -07:00",
|
return t, nil
|
||||||
"2006-1-02 15:4:5 -07:00",
|
}
|
||||||
|
}
|
||||||
|
case part2Len == 2 && part3Len == 1:
|
||||||
|
for _, layout := range []string{
|
||||||
"2006-01-2 15:04:05 -07:00",
|
"2006-01-2 15:04:05 -07:00",
|
||||||
"2006-01-2 15:04:5 -07:00",
|
"2006-01-2 15:04:5 -07:00",
|
||||||
"2006-01-2 15:4:05 -07:00",
|
"2006-01-2 15:4:05 -07:00",
|
||||||
"2006-01-2 15:4:5 -07:00",
|
"2006-01-2 15:4:5 -07:00",
|
||||||
|
} {
|
||||||
|
if t, err := parse(layout, datestr, loc); err == nil {
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case part2Len == 1 && part3Len == 2:
|
||||||
|
for _, layout := range []string{
|
||||||
|
"2006-1-02 15:04:05 -07:00",
|
||||||
|
"2006-1-02 15:4:05 -07:00",
|
||||||
|
"2006-1-02 15:04:5 -07:00",
|
||||||
|
"2006-1-02 15:4:5 -07:00",
|
||||||
|
} {
|
||||||
|
if t, err := parse(layout, datestr, loc); err == nil {
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case part2Len == 1 && part3Len == 1:
|
||||||
|
for _, layout := range []string{
|
||||||
"2006-1-2 15:04:05 -07:00",
|
"2006-1-2 15:04:05 -07:00",
|
||||||
"2006-1-2 15:04:5 -07:00",
|
"2006-1-2 15:04:5 -07:00",
|
||||||
"2006-1-2 15:4:05 -07:00",
|
"2006-1-2 15:4:05 -07:00",
|
||||||
@ -937,49 +967,73 @@ iterRunes:
|
|||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case stateDigitDashWsWsOffsetAlpha:
|
case stateDigitDashWsWsOffsetAlpha:
|
||||||
// 2015-02-18 00:12:00 +0000 UTC
|
// 2015-02-18 00:12:00 +0000 UTC
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case part2Len == 2 && part3Len == 2:
|
||||||
for _, layout := range []string{
|
for _, layout := range []string{
|
||||||
|
"2006-01-02 15:04:05 -0700 MST",
|
||||||
|
"2006-01-02 15:04:5 -0700 MST",
|
||||||
|
"2006-01-02 15:4:05 -0700 MST",
|
||||||
|
"2006-01-02 15:4:5 -0700 MST",
|
||||||
"2006-01-02 15:04:05 +0000 GMT",
|
"2006-01-02 15:04:05 +0000 GMT",
|
||||||
"2006-01-02 15:04:5 +0000 GMT",
|
"2006-01-02 15:04:5 +0000 GMT",
|
||||||
"2006-01-02 15:4:05 +0000 GMT",
|
"2006-01-02 15:4:05 +0000 GMT",
|
||||||
"2006-01-02 15:4:5 +0000 GMT",
|
"2006-01-02 15:4:5 +0000 GMT",
|
||||||
"2006-1-02 15:04:05 +0000 GMT",
|
} {
|
||||||
"2006-1-02 15:4:05 +0000 GMT",
|
if t, err := parse(layout, datestr, loc); err == nil {
|
||||||
"2006-1-02 15:04:5 +0000 GMT",
|
return t, nil
|
||||||
"2006-1-02 15:4:5 +0000 GMT",
|
}
|
||||||
|
}
|
||||||
|
case part2Len == 2 && part3Len == 1:
|
||||||
|
for _, layout := range []string{
|
||||||
|
"2006-01-2 15:04:05 -0700 MST",
|
||||||
|
"2006-01-2 15:04:5 -0700 MST",
|
||||||
|
"2006-01-2 15:4:05 -0700 MST",
|
||||||
|
"2006-01-2 15:4:5 -0700 MST",
|
||||||
"2006-01-2 15:04:05 +0000 GMT",
|
"2006-01-2 15:04:05 +0000 GMT",
|
||||||
"2006-01-2 15:04:5 +0000 GMT",
|
"2006-01-2 15:04:5 +0000 GMT",
|
||||||
"2006-01-2 15:4:05 +0000 GMT",
|
"2006-01-2 15:4:05 +0000 GMT",
|
||||||
"2006-01-2 15:4:5 +0000 GMT",
|
"2006-01-2 15:4:5 +0000 GMT",
|
||||||
|
} {
|
||||||
|
if t, err := parse(layout, datestr, loc); err == nil {
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case part2Len == 1 && part3Len == 2:
|
||||||
|
for _, layout := range []string{
|
||||||
|
"2006-1-02 15:04:05 -0700 MST",
|
||||||
|
"2006-1-02 15:4:05 -0700 MST",
|
||||||
|
"2006-1-02 15:04:5 -0700 MST",
|
||||||
|
"2006-1-02 15:4:5 -0700 MST",
|
||||||
|
"2006-1-02 15:04:05 +0000 GMT",
|
||||||
|
"2006-1-02 15:4:05 +0000 GMT",
|
||||||
|
"2006-1-02 15:04:5 +0000 GMT",
|
||||||
|
"2006-1-02 15:4:5 +0000 GMT",
|
||||||
|
} {
|
||||||
|
if t, err := parse(layout, datestr, loc); err == nil {
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case part2Len == 1 && part3Len == 1:
|
||||||
|
for _, layout := range []string{
|
||||||
|
"2006-1-2 15:04:05 -0700 MST",
|
||||||
|
"2006-1-2 15:04:5 -0700 MST",
|
||||||
|
"2006-1-2 15:4:05 -0700 MST",
|
||||||
|
"2006-1-2 15:4:5 -0700 MST",
|
||||||
"2006-1-2 15:04:05 +0000 GMT",
|
"2006-1-2 15:04:05 +0000 GMT",
|
||||||
"2006-1-2 15:04:5 +0000 GMT",
|
"2006-1-2 15:04:5 +0000 GMT",
|
||||||
"2006-1-2 15:4:05 +0000 GMT",
|
"2006-1-2 15:4:05 +0000 GMT",
|
||||||
"2006-1-2 15:4:5 +0000 GMT",
|
"2006-1-2 15:4:5 +0000 GMT",
|
||||||
|
|
||||||
"2006-01-02 15:04:05 -0700 UTC",
|
|
||||||
"2006-01-02 15:04:5 -0700 UTC",
|
|
||||||
"2006-01-02 15:4:05 -0700 UTC",
|
|
||||||
"2006-01-02 15:4:5 -0700 UTC",
|
|
||||||
"2006-1-02 15:04:05 -0700 UTC",
|
|
||||||
"2006-1-02 15:4:05 -0700 UTC",
|
|
||||||
"2006-1-02 15:04:5 -0700 UTC",
|
|
||||||
"2006-1-02 15:4:5 -0700 UTC",
|
|
||||||
"2006-01-2 15:04:05 -0700 UTC",
|
|
||||||
"2006-01-2 15:04:5 -0700 UTC",
|
|
||||||
"2006-01-2 15:4:05 -0700 UTC",
|
|
||||||
"2006-01-2 15:4:5 -0700 UTC",
|
|
||||||
"2006-1-2 15:04:05 -0700 UTC",
|
|
||||||
"2006-1-2 15:04:5 -0700 UTC",
|
|
||||||
"2006-1-2 15:4:05 -0700 UTC",
|
|
||||||
"2006-1-2 15:4:5 -0700 UTC",
|
|
||||||
} {
|
} {
|
||||||
if t, err := parse(layout, datestr, loc); err == nil {
|
if t, err := parse(layout, datestr, loc); err == nil {
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case stateDigitDashWsWsOffsetColonAlpha:
|
case stateDigitDashWsWsOffsetColonAlpha:
|
||||||
// 2015-02-18 00:12:00 +00:00 UTC
|
// 2015-02-18 00:12:00 +00:00 UTC
|
||||||
@ -1530,7 +1584,7 @@ iterRunes:
|
|||||||
|
|
||||||
case stateWeekdayAbbrevCommaOffsetZone:
|
case stateWeekdayAbbrevCommaOffsetZone:
|
||||||
// Tue, 11 Jul 2017 16:28:13 +0200 (CEST)
|
// Tue, 11 Jul 2017 16:28:13 +0200 (CEST)
|
||||||
if dayLen == 1 {
|
if part3Len == 1 {
|
||||||
return parse("Mon, 2 Jan 2006 15:04:05 -0700 (MST)", datestr, loc)
|
return parse("Mon, 2 Jan 2006 15:04:05 -0700 (MST)", datestr, loc)
|
||||||
}
|
}
|
||||||
return parse("Mon, _2 Jan 2006 15:04:05 -0700 (MST)", datestr, loc)
|
return parse("Mon, _2 Jan 2006 15:04:05 -0700 (MST)", datestr, loc)
|
||||||
|
@ -458,8 +458,14 @@ func TestParse(t *testing.T) {
|
|||||||
ts = MustParse("2014-04-26 17:24:37.1 UTC")
|
ts = MustParse("2014-04-26 17:24:37.1 UTC")
|
||||||
assert.Equal(t, "2014-04-26 17:24:37.1 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
assert.Equal(t, "2014-04-26 17:24:37.1 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
|
||||||
ts = MustParse("2014-04-26 17:24:37.123 +0800")
|
ts = MustParse("2014-04-26 09:04:37.123 +0800")
|
||||||
assert.Equal(t, "2014-04-26 09:24:37.123 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
assert.Equal(t, "2014-04-26 01:04:37.123 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2014-04-26 9:04:37.123 +0800")
|
||||||
|
assert.Equal(t, "2014-04-26 01:04:37.123 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2014-04-26 09:4:37.123 +0800")
|
||||||
|
assert.Equal(t, "2014-04-26 01:04:37.123 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2014-04-26 9:4:37.123 +0800")
|
||||||
|
assert.Equal(t, "2014-04-26 01:04:37.123 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
|
||||||
ts = MustParse("2014-04-26 17:24:37.123 -0800")
|
ts = MustParse("2014-04-26 17:24:37.123 -0800")
|
||||||
assert.Equal(t, "2014-04-27 01:24:37.123 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
assert.Equal(t, "2014-04-27 01:24:37.123 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
@ -473,16 +479,40 @@ func TestParse(t *testing.T) {
|
|||||||
ts = MustParse("2017-07-19 03:21:51+00:00")
|
ts = MustParse("2017-07-19 03:21:51+00:00")
|
||||||
assert.Equal(t, "2017-07-19 03:21:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
assert.Equal(t, "2017-07-19 03:21:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
|
||||||
ts = MustParse("2017-07-19 03:21:51 +00:00 UTC")
|
ts = MustParse("2017-07-09 03:01:51 +00:00 UTC")
|
||||||
assert.Equal(t, "2017-07-19 03:21:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
assert.Equal(t, "2017-07-09 03:01:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2017-7-09 03:01:51 +00:00 UTC")
|
||||||
|
assert.Equal(t, "2017-07-09 03:01:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2017-07-9 03:01:51 +00:00 UTC")
|
||||||
|
assert.Equal(t, "2017-07-09 03:01:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2017-7-9 03:01:51 +00:00 UTC")
|
||||||
|
assert.Equal(t, "2017-07-09 03:01:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
|
||||||
ts = MustParse("2015-02-18 00:12:00 +0000 GMT")
|
ts = MustParse("2017-07-19 03:01:51 +00:00 UTC")
|
||||||
assert.Equal(t, "2015-02-18 00:12:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
assert.Equal(t, "2017-07-19 03:01:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2017-07-19 3:01:51 +00:00 UTC")
|
||||||
|
assert.Equal(t, "2017-07-19 03:01:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2017-07-19 03:1:51 +00:00 UTC")
|
||||||
|
assert.Equal(t, "2017-07-19 03:01:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2017-07-19 3:1:51 +00:00 UTC")
|
||||||
|
assert.Equal(t, "2017-07-19 03:01:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
|
||||||
// Golang Native Format
|
// Golang Native Format
|
||||||
ts = MustParse("2015-02-18 00:12:00 +0000 UTC")
|
ts = MustParse("2015-02-18 00:12:00 +0000 UTC")
|
||||||
assert.Equal(t, "2015-02-18 00:12:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
assert.Equal(t, "2015-02-18 00:12:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
|
||||||
|
ts = MustParse("2015-02-18 00:12:00 +0000 GMT")
|
||||||
|
assert.Equal(t, "2015-02-18 00:12:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
|
||||||
|
ts = MustParse("2015-02-08 03:02:00 +0300 MSK")
|
||||||
|
assert.Equal(t, "2015-02-08 00:02:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2015-2-08 03:02:00 +0300 MSK")
|
||||||
|
assert.Equal(t, "2015-02-08 00:02:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2015-02-8 03:02:00 +0300 MSK")
|
||||||
|
assert.Equal(t, "2015-02-08 00:02:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2015-2-8 03:02:00 +0300 MSK")
|
||||||
|
assert.Equal(t, "2015-02-08 00:02:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
|
||||||
ts = MustParse("2014-12-16 06:20:00 UTC")
|
ts = MustParse("2014-12-16 06:20:00 UTC")
|
||||||
assert.Equal(t, "2014-12-16 06:20:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
assert.Equal(t, "2014-12-16 06:20:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
|
||||||
@ -511,8 +541,14 @@ func TestParse(t *testing.T) {
|
|||||||
_, err = ParseAny("2014-13-13 08:20:13,787") // month 13 doesn't exist so error
|
_, err = ParseAny("2014-13-13 08:20:13,787") // month 13 doesn't exist so error
|
||||||
assert.NotEqual(t, nil, err)
|
assert.NotEqual(t, nil, err)
|
||||||
|
|
||||||
ts = MustParse("2014-05-11 08:20:13 +00:00")
|
ts = MustParse("2014-05-01 08:02:13 +00:00")
|
||||||
assert.Equal(t, "2014-05-11 08:20:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
assert.Equal(t, "2014-05-01 08:02:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2014-5-01 08:02:13 +00:00")
|
||||||
|
assert.Equal(t, "2014-05-01 08:02:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2014-05-1 08:02:13 +00:00")
|
||||||
|
assert.Equal(t, "2014-05-01 08:02:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
ts = MustParse("2014-5-1 08:02:13 +00:00")
|
||||||
|
assert.Equal(t, "2014-05-01 08:02:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
|
||||||
ts = MustParse("2014-05-11 08:20:13 +0000")
|
ts = MustParse("2014-05-11 08:20:13 +0000")
|
||||||
assert.Equal(t, "2014-05-11 08:20:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
assert.Equal(t, "2014-05-11 08:20:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
|
||||||
|
Loading…
Reference in New Issue
Block a user