1717 * limitations under the License.
1818 */
1919
20- import { int } from '../integer' ;
20+ import { int , isInt } from '../integer' ;
2121import { Date , LocalDateTime , LocalTime } from '../temporal-types' ;
22+ import { assertNumberOrInteger } from './util' ;
23+ import { newError } from '../error' ;
2224
2325/*
2426 Code in this util should be compatible with code in the database that uses JSR-310 java.time APIs.
@@ -31,10 +33,41 @@ import {Date, LocalDateTime, LocalTime} from '../temporal-types';
3133 conversion functions.
3234 */
3335
36+ class ValueRange {
37+
38+ constructor ( min , max ) {
39+ this . _minNumber = min ;
40+ this . _maxNumber = max ;
41+ this . _minInteger = int ( min ) ;
42+ this . _maxInteger = int ( max ) ;
43+ }
44+
45+ contains ( value ) {
46+ if ( isInt ( value ) ) {
47+ return value . greaterThanOrEqual ( this . _minInteger ) && value . lessThanOrEqual ( this . _maxInteger ) ;
48+ } else {
49+ return value >= this . _minNumber && value <= this . _maxNumber ;
50+ }
51+ }
52+
53+ toString ( ) {
54+ return `[${ this . _minNumber } , ${ this . _maxNumber } ]` ;
55+ }
56+ }
57+
58+ const YEAR_RANGE = new ValueRange ( - 999999999 , 999999999 ) ;
59+ const MONTH_OF_YEAR_RANGE = new ValueRange ( 1 , 12 ) ;
60+ const DAY_OF_MONTH_RANGE = new ValueRange ( 1 , 31 ) ;
61+ const HOUR_OF_DAY_RANGE = new ValueRange ( 0 , 23 ) ;
62+ const MINUTE_OF_HOUR_RANGE = new ValueRange ( 0 , 59 ) ;
63+ const SECOND_OF_MINUTE_RANGE = new ValueRange ( 0 , 59 ) ;
64+ const NANOSECOND_OF_SECOND_RANGE = new ValueRange ( 0 , 999999999 ) ;
65+
3466const MINUTES_PER_HOUR = 60 ;
3567const SECONDS_PER_MINUTE = 60 ;
3668const SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR ;
3769const NANOS_PER_SECOND = 1000000000 ;
70+ const NANOS_PER_MILLISECOND = 1000000 ;
3871const NANOS_PER_MINUTE = NANOS_PER_SECOND * SECONDS_PER_MINUTE ;
3972const NANOS_PER_HOUR = NANOS_PER_MINUTE * MINUTES_PER_HOUR ;
4073const DAYS_0000_TO_1970 = 719528 ;
@@ -264,6 +297,105 @@ export function dateToIsoString(year, month, day) {
264297 return `${ yearString } -${ monthString } -${ dayString } ` ;
265298}
266299
300+ /**
301+ * Get the total number of nanoseconds from the milliseconds of the given standard JavaScript date and optional nanosecond part.
302+ * @param {global.Date } standardDate the standard JavaScript date.
303+ * @param {Integer|number|undefined } nanoseconds the optional number of nanoseconds.
304+ * @return {Integer|number } the total amount of nanoseconds.
305+ */
306+ export function totalNanoseconds ( standardDate , nanoseconds ) {
307+ nanoseconds = ( nanoseconds || 0 ) ;
308+ const nanosFromMillis = standardDate . getMilliseconds ( ) * NANOS_PER_MILLISECOND ;
309+ return isInt ( nanoseconds ) ? nanoseconds . add ( nanosFromMillis ) : nanoseconds + nanosFromMillis ;
310+ }
311+
312+ /**
313+ * Get the time zone offset in seconds from the given standard JavaScript date.
314+ * @param {global.Date } standardDate the standard JavaScript date.
315+ * @return {number } the time zone offset in seconds.
316+ */
317+ export function timeZoneOffsetInSeconds ( standardDate ) {
318+ return standardDate . getTimezoneOffset ( ) * SECONDS_PER_MINUTE ;
319+ }
320+
321+ /**
322+ * Assert that the year value is valid.
323+ * @param {Integer|number } year the value to check.
324+ * @return {Integer|number } the value of the year if it is valid. Exception is thrown otherwise.
325+ */
326+ export function assertValidYear ( year ) {
327+ return assertValidTemporalValue ( year , YEAR_RANGE , 'Year' ) ;
328+ }
329+
330+ /**
331+ * Assert that the month value is valid.
332+ * @param {Integer|number } month the value to check.
333+ * @return {Integer|number } the value of the month if it is valid. Exception is thrown otherwise.
334+ */
335+ export function assertValidMonth ( month ) {
336+ return assertValidTemporalValue ( month , MONTH_OF_YEAR_RANGE , 'Month' ) ;
337+ }
338+
339+ /**
340+ * Assert that the day value is valid.
341+ * @param {Integer|number } day the value to check.
342+ * @return {Integer|number } the value of the day if it is valid. Exception is thrown otherwise.
343+ */
344+ export function assertValidDay ( day ) {
345+ return assertValidTemporalValue ( day , DAY_OF_MONTH_RANGE , 'Day' ) ;
346+ }
347+
348+ /**
349+ * Assert that the hour value is valid.
350+ * @param {Integer|number } hour the value to check.
351+ * @return {Integer|number } the value of the hour if it is valid. Exception is thrown otherwise.
352+ */
353+ export function assertValidHour ( hour ) {
354+ return assertValidTemporalValue ( hour , HOUR_OF_DAY_RANGE , 'Hour' ) ;
355+ }
356+
357+ /**
358+ * Assert that the minute value is valid.
359+ * @param {Integer|number } minute the value to check.
360+ * @return {Integer|number } the value of the minute if it is valid. Exception is thrown otherwise.
361+ */
362+ export function assertValidMinute ( minute ) {
363+ return assertValidTemporalValue ( minute , MINUTE_OF_HOUR_RANGE , 'Minute' ) ;
364+ }
365+
366+ /**
367+ * Assert that the second value is valid.
368+ * @param {Integer|number } second the value to check.
369+ * @return {Integer|number } the value of the second if it is valid. Exception is thrown otherwise.
370+ */
371+ export function assertValidSecond ( second ) {
372+ return assertValidTemporalValue ( second , SECOND_OF_MINUTE_RANGE , 'Second' ) ;
373+ }
374+
375+ /**
376+ * Assert that the nanosecond value is valid.
377+ * @param {Integer|number } nanosecond the value to check.
378+ * @return {Integer|number } the value of the nanosecond if it is valid. Exception is thrown otherwise.
379+ */
380+ export function assertValidNanosecond ( nanosecond ) {
381+ return assertValidTemporalValue ( nanosecond , NANOSECOND_OF_SECOND_RANGE , 'Nanosecond' ) ;
382+ }
383+
384+ /**
385+ * Check if the given value is of expected type and is in the expected range.
386+ * @param {Integer|number } value the value to check.
387+ * @param {ValueRange } range the range.
388+ * @param {string } name the name of the value.
389+ * @return {Integer|number } the value if valid. Exception is thrown otherwise.
390+ */
391+ function assertValidTemporalValue ( value , range , name ) {
392+ assertNumberOrInteger ( value , name ) ;
393+ if ( ! range . contains ( value ) ) {
394+ throw newError ( `${ name } is expected to be in range ${ range } but was: ${ value } ` ) ;
395+ }
396+ return value ;
397+ }
398+
267399/**
268400 * Converts given local time into a single integer representing this same time in seconds of the day. Nanoseconds are skipped.
269401 * @param {Integer|number|string } hour the hour of the local time.
0 commit comments