Skip to content

Conversation

@russcam
Copy link
Contributor

@russcam russcam commented Dec 21, 2017

This commit changes the implementation of Time within the client for better consistency with Elasticsearch's TimeValue. The Time type in NEST 5.x is used to represent both Elasticsearch's TimeValue (which allows from nanos up to days as unit), and as time modifiers within DateMath expressions, for which Elasticsearch accepts units of y (years) M (months), w (weeks), d (days), h/H (hours), m (minutes) and s (seconds).

  • When converting from a TimeSpan to Time, the serialized value is a whole number with the largest unit of days. This fixes the implementation to be in line with Elasticsearch 5.0+ with Keep input time unit when parsing TimeValues elasticsearch#19102 where weeks was removed as a supported unit for TimeValue.

  • When constructing a Time using the constructor that takes a double of milliseconds, make the implementation consistent with the implicit conversion from double implementation; in the case of -1, both should be Time.MinusOne and the case of 0, both should be Time.Zero. If needing to express -1ms or 0ms, the constructor taking a factor and unit, or the constructor taking a string value with unit should be used.

  • When constructing a Time from double or TimeSpan, try to reduce the value to a whole number factor and largest represented unit (up to unit of days). For values smaller than 1 nanosecond, retain the factor as a fraction of nanoseconds.

  • When converting a Time to a TimeSpan, round the value to the nearest TimeSpan tick for microseconds and nanoseconds, and milliseconds for all other units.

  • When converting to a Time within a DateMath expression using Time.ToFirstUnitYieldingInteger(), when the value is fractional nanoseconds, round to the nearest nanosecond. Although this method is only used within the client for DateMath expressions and can return times with units smaller than a second (the smallest unit that DateMath within Elasticsearch accepts), the method is public so could be used by consumers for purposes other than DateMath. Because of this, don't break the implementation for units smaller than one second.

  • Allow the implicit conversion from string and the constructor that takes a string to continue to accept fractional units, which can be returned from Elasticsearch as per TimeValue's toString implementation https://github.com/elastic/elasticsearch/blob/f2501130399f6e3788e110d74dd62b3aad66804a/core/src/main/java/org/elasticsearch/common/unit/TimeValue.java#L253-L290

  • Update documentation

Closes #2818

This commit changes the implementation of Time within the client for better consistency with Elasticsearch's TimeValue. The Time type in NEST 5.x is used to represent both Elasticsearch's TimeValue (which allows from nanos up to days as unit), and as time modifiers within DateMath expressions, for which Elasticsearch accepts units of  y (years) M (months), w (weeks), d (days), h/H (hours), m (minutes) and s (seconds).

- When converting from a TimeSpan to Time, the serialized value is a whole number with the largest unit of days. This fixes the implementation to be in line with Elasticsearch 5.0+ with elastic/elasticsearch#19102 where weeks was removed as a supported unit for TimeValue.

- When constructing a Time using the constructor that takes a double of milliseconds, make the implementation consistent with the implicit conversion from double implementation; in the case of -1, both should be Time.MinusOne and the case of 0, both should be Time.Zero. If needing to express -1ms or 0ms, the constructor taking a factor and unit, or the constructor taking a string value with unit should be used.

- When constructing a Time from double or TimeSpan, try to reduce the value to a whole number factor and largest represented unit (up to unit of days). For values smaller than 1 nanosecond, retain the factor as a fraction of nanoseconds.

- When converting a Time to a TimeSpan, round the value to the nearest TimeSpan tick for microseconds and nanoseconds, and milliseconds for all other units.

- When converting to a Time within a DateMath expression using Time.ToFirstUnitYieldingInteger(), when the value is fractional nanoseconds, round to the nearest nanosecond. Although this method is only used within the client for DateMath expressions and can return times with units smaller than a second (the smallest unit that DateMath within Elasticsearch accepts), the method is public so could be used by consumers for purposes other than DateMath. Because of this, don't break the implementation for units smaller than one second.

- Allow the implicit conversion from string and the constructor that takes a string to continue to accept fractional units, which can be returned from Elasticsearch as per TimeValue's toString implementation https://github.com/elastic/elasticsearch/blob/f2501130399f6e3788e110d74dd62b3aad66804a/core/src/main/java/org/elasticsearch/common/unit/TimeValue.java#L253-L290

- Update documentation

Closes #2818
@russcam
Copy link
Contributor Author

russcam commented Dec 21, 2017

The implementation of Time should be updated for 6.x, to split out into two types:

  • a type to represent Elasticsearch's TimeValue
  • a type to represent times within NEST's DateMath

if (Math.Abs(milliseconds) < FLOAT_TOLERANCE) return Time.Zero;
if (Math.Abs(milliseconds - (-1)) < FLOAT_TOLERANCE) return MinusOne;
if (Math.Abs(milliseconds) < FLOAT_TOLERANCE) return Zero;
return new Time(milliseconds);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can now simply return new Time(milliseconds);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Member

@Mpdreamz Mpdreamz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

if (Math.Abs(milliseconds) < FLOAT_TOLERANCE) return Time.Zero;
if (Math.Abs(milliseconds - (-1)) < FLOAT_TOLERANCE) return MinusOne;
if (Math.Abs(milliseconds) < FLOAT_TOLERANCE) return Zero;
return new Time(milliseconds);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@Mpdreamz
Copy link
Member

Awesome work @russcam

When constructing a Time using the constructor that takes a double of milliseconds, make the implementation consistent with the implicit conversion from double implementation; in the case of -1, both should be Time.MinusOne and the case of 0, both should be Time.Zero. If needing to express -1ms or 0ms, the constructor taking a factor and unit, or the constructor taking a string value with unit should be used.

I remember going to some effort to build it as it was since the constructor mentions passing milliseconds but the way this PR normalizes it makes a lot more sense

russcam and others added 3 commits December 22, 2017 12:57
Add XML documentation to Time methods to describe what ToTimeSpan() and ToFirstUnitYieldingInteger() will do
Simplify multiplication by reciprocals
ToFirstUnitYieldingInteger() is used in NEST only within DateMath expressions. Support whole values in months and weeks.
@russcam russcam merged commit 766833c into 5.x Dec 22, 2017
@Mpdreamz Mpdreamz deleted the fix/5.x-whole-time-units branch January 30, 2018 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants