Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Date enhancements and support for Unix Timestamps #791

Merged
merged 1 commit into from
Jan 7, 2016

Conversation

galenandrew
Copy link
Contributor

Revised

This PR includes the following changes:

  • Support for decimals in date() validation
  • New constraint for date.timestamp() that supports both javascript and unix timestamps
  • Updated Tests, API documentation, and added date example

Note: Because javascript timestamps are millisecond-based and unix timestamps are second-based, the timestamp() constraint accepts an optional type parameter to ensure proper date conversion for the given input value.

closes #789

@galenandrew galenandrew changed the title Date/Timestamp enhancements and support for Unix Timestamps [closes #789] Date/Timestamp enhancements and support for Unix Timestamps Dec 31, 2015

value = parseInt(value, 10);
value = Number(value);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed this to the Number constructor because parseInt drops the decimals. After reviewing performance I've updated it to use parseFloat.

@Marsup
Copy link
Collaborator

Marsup commented Jan 1, 2016

Thinking about it, can't we just use the existing unit without adding any new api ?

@galenandrew
Copy link
Contributor Author

@Marsup PR has been updated and downstream merged with your recent commits to master.

I've removed the approach that uses unit and simplified the new timestamp constraint implementation.

@Marsup
Copy link
Collaborator

Marsup commented Jan 5, 2016

So what happened to my last comment ?

@galenandrew
Copy link
Contributor Author

I'm not sure I understand what you mean? Please explain.

@Marsup
Copy link
Collaborator

Marsup commented Jan 5, 2016

I don't think a new API is needed, just using the existing unit.

@galenandrew
Copy link
Contributor Author

I agree that replicating the unit API within the date type is not needed, however I respectfully disagree about the need for a new API for timestamps. The date type has an explicit iso constraint and should have an explicit timestamp constraint as well.

This PR is clean, functional and has 100% test coverage.

@galenandrew
Copy link
Contributor Author

If you have objective reasoning for a different approach on handling timestamps let's discuss it. For instance, getting rid of the type parameter in the timestamp API and using the built in unit to handle the multiplier. This would result in something like the following for unix timestamps: Joi.date().timestamp().unit('seconds').

@Marsup
Copy link
Collaborator

Marsup commented Jan 5, 2016

Joi.date().timestamp('unix') is essentially the same as Joi.date().unit('s') except you're adding a new API and a new concept of "unix timestamp" that not everyone might be familiar with. Joi.date() just defaults to unit('ms') when it's a number.

ISO is a strict format applied on a string hence its special treatment, a number is not timestamp by itself, any number is a timestamp. Actually, if you want a strict validation on that, I'm just now seeing that this could already be achieved by a Joi.date().format('X') or Joi.date().format('x').

using the built in unit to handle the multiplier

I do mean that the unit should translate to a multiplier.

FWIW I'm not questioning the quality of the PR here, just the content.

@kanongil
Copy link
Contributor

kanongil commented Jan 5, 2016

@Marsup I am pretty sure it is a bad idea to change the parsing of a date depending on the .unit() value, given that it is only for annotation purposes.

Also, Joi.date().format('X') won't work for fractional timestamps.

@Marsup
Copy link
Collaborator

Marsup commented Jan 5, 2016

It's been for annotation so far, is there any valid reason not to use it as it already exists ?
Fractional as in x/y ? Moment seems to support floats according to their docs, I didn't test.

@kanongil
Copy link
Contributor

kanongil commented Jan 5, 2016

Fractional, as in 123.45, which Joi never passes on to moment.

@Marsup
Copy link
Collaborator

Marsup commented Jan 5, 2016

Oh yeah, but with this patch it would.

@galenandrew
Copy link
Contributor Author

While using unit to set the timestamp multiplier is a valid approach, what are the reasons we should not add an explicit timestamp constraint?

To me, Joi.date().timestamp() is more descriptive about the function of this constraint vs Joi.date().unit('s').

@galenandrew galenandrew changed the title Date/Timestamp enhancements and support for Unix Timestamps Date enhancements and support for Unix Timestamps Jan 6, 2016
@Marsup
Copy link
Collaborator

Marsup commented Jan 6, 2016

I don't mind the timestamp per se, the flag behind it seems like a useless duplication of unit though. As common ground I'd propose timestamp takes whatever it can and translate it to unit, OK for everyone ?

@galenandrew
Copy link
Contributor Author

That can work. So to confirm, is the following acceptable? If so, I'll update the PR accordingly.

The timestamp constraint will apply a numeric regex (/^[+-]?\d+(\.\d+)?$/) and any argument passed will set the existing unit flag (which will be used to control the multiplier).

So for instance…
Joi.date().timestamp('seconds') or Joi.date().timestamp().unit('seconds') will explicitly test for numeric values AND set the existing unit to seconds which will as a result trigger the multiplier. In other words, a stricter validation (eg non-timestamp values will fail).

Joi.date().unit('seconds') will trigger the multiplier, but not force the numeric values regex. In other words, a less strict validation (eg non-timestamp values will not fail but the multiplier may not be used based on the value format).

@kanongil
Copy link
Contributor

kanongil commented Jan 6, 2016

I'd still argue against changing the meaning of unit(…). If you decide to go ahead, remember to flag this as a breaking change.

@galenandrew
Copy link
Contributor Author

Honestly, I'm leaning that way as well. Avoiding unit feels cleaner and follows a better separation of concerns. "Piggy-backing" on unit introduces cross-over between the APIs and potential complications down the road if the functionality/purpose of one changes.

To me, the question should come down to the timestamp(...) parameter using a concept of type vs time segment – unix/javascript vs seconds/milliseconds. Type feels more descriptive, but time segment seems like it would allow for greater flexibility with the multiplier and value conversion.

@Marsup
Copy link
Collaborator

Marsup commented Jan 6, 2016

Back-channeled a bit with @kanongil, let's stick to the current form, gonna review now.

@Marsup Marsup added the feature New functionality or improvement label Jan 6, 2016
@Marsup Marsup self-assigned this Jan 6, 2016
@Marsup Marsup added this to the 7.2.0 milestone Jan 6, 2016
@Marsup Marsup added the bug Bug or defect label Jan 6, 2016
@@ -23,6 +23,12 @@ internals.isIsoDate = (() => {
return date && (date.toString() === isoString);
};
})();
internals.isTimestampAllowed = function (unit) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Inline that, it's only used once.

@galenandrew
Copy link
Contributor Author

Thanks for the review and line notes @Marsup!! I'll work on these changes and let you know when it's updated.

@galenandrew
Copy link
Contributor Author

@Marsup, PR is updated. Good call on adding some additional checks for ambiguous values. I've also updated the date.base language to be timestamp agnostic.

When all looks good let me know and I'll rebase down to a single commit so it keeps the history short.

@@ -150,6 +159,19 @@ internals.Date.prototype.iso = function () {
return obj;
};

internals.Date.prototype.timestamp = function (type) {

type = type ? type : 'javascript';
Copy link
Collaborator

Choose a reason for hiding this comment

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

type = type || 'javascript'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good call…will update.

- downstream merge and resolve conflicts
- simplify timestamp API
- refactor timestamp based on PR feedback
- update date.base language to be timestamp generic
- misc optimizations and updated tests
- revert date.base error message
@galenandrew
Copy link
Contributor Author

PR has been updated and rebased

Marsup added a commit that referenced this pull request Jan 7, 2016
Date enhancements and support for Unix Timestamps
@Marsup Marsup merged commit b616de6 into hapijs:master Jan 7, 2016
@Marsup
Copy link
Collaborator

Marsup commented Jan 7, 2016

Thanks for the hard work.

@galenandrew galenandrew deleted the timestamps branch January 7, 2016 16:09
@galenandrew
Copy link
Contributor Author

You're welcome!! Thanks for the feedback and reviewing my pull request!

@AdrieanKhisbe
Copy link
Contributor

👍

@lock
Copy link

lock bot commented Jan 9, 2020

This thread has been automatically locked due to inactivity. Please open a new issue for related bugs or questions following the new issue template instructions.

@lock lock bot locked as resolved and limited conversation to collaborators Jan 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Bug or defect feature New functionality or improvement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Date() does not validate Unix timestamp with fractional seconds (decimals)
4 participants