Skip to content

Commit

Permalink
added changes for creating Timestamp from date (#686)
Browse files Browse the repository at this point in the history
  • Loading branch information
desaikd authored Apr 12, 2021
1 parent 82b940c commit b5f6ab3
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 56 deletions.
156 changes: 100 additions & 56 deletions src/IonTimestamp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ export class Timestamp {
private _precision: TimestampPrecision;
private readonly _secondsDecimal: Decimal;

/** Creates a new Ion Timestamp with millisecond precision from a JavaScript Date.
*
* @param date a valid JavaScript date object
*/
constructor(date: Date);

/**
* Creates a new Timestamp, with precision determined by which parameters
* are provided. If a parameter is not specified, it defaults to its lowest
Expand All @@ -73,71 +79,110 @@ export class Timestamp {
constructor(
localOffset: number,
year: number,
month?: number | null,
day?: number | null,
hour?: number | null,
minutes?: number | null,
seconds?: number | Decimal | null
);

constructor(
dateOrLocalOffset: number | Date | null = null,
year: number | null = null,
month: number | null = null,
day: number | null = null,
hour: number | null = null,
minutes: number | null = null,
seconds: number | Decimal | null = null
) {
this._localOffset = localOffset;
this._year = year;

this._precision = TimestampPrecision.YEAR;
this._checkRequiredField(
"Offset",
this._localOffset,
Timestamp._MIN_OFFSET,
Timestamp._MAX_OFFSET
);
this._checkRequiredField(
"Year",
this._year,
Timestamp._MIN_YEAR,
Timestamp._MAX_YEAR
);
this._month = this._checkOptionalField(
"Month",
month,
Timestamp._MIN_MONTH,
Timestamp._MAX_MONTH,
1,
TimestampPrecision.MONTH
);
this._day = this._checkOptionalField(
"Day",
day,
Timestamp._MIN_DAY,
Timestamp._MAX_DAY,
1,
TimestampPrecision.DAY
);
this._hour = this._checkOptionalField(
"Hour",
hour,
Timestamp._MIN_HOUR,
Timestamp._MAX_HOUR,
0,
TimestampPrecision.HOUR_AND_MINUTE
);
this._minutes = this._checkOptionalField(
"Minutes",
minutes,
Timestamp._MIN_MINUTE,
Timestamp._MAX_MINUTE,
0,
TimestampPrecision.HOUR_AND_MINUTE
);
if (dateOrLocalOffset instanceof Date) {
const date = dateOrLocalOffset;
const seconds = new Decimal(
// The coefficient is the total number of milliseconds as an integer
date.getSeconds() + date.getMilliseconds(),
// And the exponent is 0 to indicate the scale of that integer
0
);

this._localOffset = date.getTimezoneOffset() * -1;
this._year = date.getFullYear();
this._month = date.getMonth() + 1;
this._day = date.getDate();
this._hour = date.getHours();
this._minutes = date.getMinutes();
this._secondsDecimal = seconds;
this._precision = TimestampPrecision.YEAR;
} else {
const localOffset = dateOrLocalOffset;

if (typeof seconds === "number") {
if (!Number.isInteger(seconds)) {
if (localOffset === null) {
throw new Error(
"The provided seconds number was not an integer (" + seconds + ")"
"Timestamp's constructor was called without localOffset"
);
} else if (year === null) {
throw new Error("Timestamp's constructor was called without year");
} else {
this._localOffset = localOffset;
this._year = year;
}
this._secondsDecimal = new Decimal(seconds, 0);
} else {
if (seconds !== null) {
this._secondsDecimal = seconds;

this._precision = TimestampPrecision.YEAR;
this._checkRequiredField(
"Offset",
this._localOffset,
Timestamp._MIN_OFFSET,
Timestamp._MAX_OFFSET
);
this._checkRequiredField(
"Year",
this._year,
Timestamp._MIN_YEAR,
Timestamp._MAX_YEAR
);
this._month = this._checkOptionalField(
"Month",
month,
Timestamp._MIN_MONTH,
Timestamp._MAX_MONTH,
1,
TimestampPrecision.MONTH
);
this._day = this._checkOptionalField(
"Day",
day,
Timestamp._MIN_DAY,
Timestamp._MAX_DAY,
1,
TimestampPrecision.DAY
);
this._hour = this._checkOptionalField(
"Hour",
hour,
Timestamp._MIN_HOUR,
Timestamp._MAX_HOUR,
0,
TimestampPrecision.HOUR_AND_MINUTE
);
this._minutes = this._checkOptionalField(
"Minutes",
minutes,
Timestamp._MIN_MINUTE,
Timestamp._MAX_MINUTE,
0,
TimestampPrecision.HOUR_AND_MINUTE
);

if (typeof seconds === "number") {
if (!Number.isInteger(seconds)) {
throw new Error(
"The provided seconds number was not an integer (" + seconds + ")"
);
}
this._secondsDecimal = new Decimal(seconds, 0);
} else {
if (seconds !== null) {
this._secondsDecimal = seconds;
}
}
}
if (this._secondsDecimal === null || this._secondsDecimal === undefined) {
Expand Down Expand Up @@ -184,7 +229,6 @@ export class Timestamp {
Timestamp._MAX_YEAR
);
}

/**
* Parses a string and returns a corresponding Timestamp object.
* The provided string must be a text-encoded Timestamp as specified
Expand Down
14 changes: 14 additions & 0 deletions test/IonTimestamp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,18 @@ describe("Timestamp", () => {
assert.deepEqual(ts.getSecondsDecimal(), ion.Decimal.parse('45'));
assert.deepEqual(ts._getFractionalSeconds(), ion.Decimal.ZERO);
});
it('constructor with Date', () => {
const date = new Date(2000, 0, 1, 12, 30, 45);
let timestamp1 = new ion.Timestamp(date.getTimezoneOffset() * -1, 2000, 1, 1, 12, 30, 45);
let timestamp2 = new ion.Timestamp(date);
assert.isTrue(timestamp1!.equals(timestamp2!));

const date2 = new Date(2000, 0, 1, 12, 30, 20, 20);
let timestamp3 = new ion.Timestamp(date2.getTimezoneOffset() * -1, 2000, 1, 1, 12, 30, new ion.Decimal(
40,
0
));
let timestamp4 = new ion.Timestamp(date2);
assert.isTrue(timestamp3!.equals(timestamp4!));
});
});

0 comments on commit b5f6ab3

Please sign in to comment.