Makes `m` case sensitive in TimeValue

The reason for this change is that currently if a user specifies e.g.`2M`
meaning 2 months as a time value instead of throwing an exception
explaining that time units in months are not supported (due to months
having variable time spans) we instead will parse this to 2 minutes.
This could be surprising to a user and could mean put a lot of load on
the cluster performing a task that was never intended and whose results
will be useless anyway.

It is generally accepted that `m` indicates minutes and `M` indicates
months with time values so this is consistent with the expectations a
user might have around specifying time units.

A concrete example of where this causes issues is in the decay score
function which uses TimeValue to parse the scale and offset parameters
of the decay into millisecond values to use in the calculation.

Relates to #19619
This commit is contained in:
Colin Goodheart-Smithe 2016-07-28 11:23:06 +01:00
parent 9fa33b6d07
commit eab5ceb9de
2 changed files with 15 additions and 5 deletions

View File

@ -326,7 +326,10 @@ public class TimeValue implements Writeable {
return new TimeValue(parse(sValue, normalized, 2), TimeUnit.MILLISECONDS);
} else if (normalized.endsWith("s")) {
return new TimeValue(parse(sValue, normalized, 1), TimeUnit.SECONDS);
} else if (normalized.endsWith("m")) {
} else if (sValue.endsWith("m")) {
// parsing minutes should be case sensitive as `M` is generally
// accepted to mean months not minutes. This is the only case where
// the upper and lower case forms indicate different time units
return new TimeValue(parse(sValue, normalized, 1), TimeUnit.MINUTES);
} else if (normalized.endsWith("h")) {
return new TimeValue(parse(sValue, normalized, 1), TimeUnit.HOURS);

View File

@ -92,10 +92,6 @@ public class TimeValueTests extends ESTestCase {
TimeValue.parseTimeValue("10 m", null, "test"));
assertEquals(new TimeValue(10, TimeUnit.MINUTES),
TimeValue.parseTimeValue("10m", null, "test"));
assertEquals(new TimeValue(10, TimeUnit.MINUTES),
TimeValue.parseTimeValue("10 M", null, "test"));
assertEquals(new TimeValue(10, TimeUnit.MINUTES),
TimeValue.parseTimeValue("10M", null, "test"));
assertEquals(new TimeValue(10, TimeUnit.HOURS),
TimeValue.parseTimeValue("10 h", null, "test"));
@ -115,6 +111,17 @@ public class TimeValueTests extends ESTestCase {
assertEquals(new TimeValue(10, TimeUnit.DAYS),
TimeValue.parseTimeValue("10D", null, "test"));
// Time values of months should throw an exception as months are not
// supported. Note that this is the only unit that is not case sensitive
// as `m` is the only character that is overloaded in terms of which
// time unit is expected between the upper and lower case versions
expectThrows(ElasticsearchParseException.class, () -> {
TimeValue.parseTimeValue("10 M", null, "test");
});
expectThrows(ElasticsearchParseException.class, () -> {
TimeValue.parseTimeValue("10M", null, "test");
});
final int length = randomIntBetween(0, 8);
final String zeros = new String(new char[length]).replace('\0', '0');
assertTrue(TimeValue.parseTimeValue("-" + zeros + "1", null, "test") == TimeValue.MINUS_ONE);