Skip to content

Commit 67d732d

Browse files
therveci.datadog-api-spec
andauthored
Fix datetime handling more broadly (#1203)
* Fix datetime handling more broadly We want the custom date object to be able to roundtrip the date betweem responses and requests. Instead of doing calculations, let's just store the original string to send it back when needed. * pre-commit fixes * Remove pad util --------- Co-authored-by: ci.datadog-api-spec <[email protected]>
1 parent 1a2c6cc commit 67d732d

File tree

3 files changed

+33
-113
lines changed

3 files changed

+33
-113
lines changed
Lines changed: 20 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
21
export class UnparsedObject {
3-
_data:any;
4-
constructor(data:any) {
2+
_data: any;
3+
constructor(data: any) {
54
this._data = data;
65
}
76
}
@@ -13,73 +12,36 @@ export type AttributeTypeMap = {
1312
required?: boolean;
1413
format?: string;
1514
};
16-
}
15+
};
1716

18-
export const isBrowser: boolean = typeof window !== "undefined" && typeof window.document !== "undefined";
17+
export const isBrowser: boolean =
18+
typeof window !== "undefined" && typeof window.document !== "undefined";
1919

20-
export const isNode: boolean = typeof process !== "undefined" && process.release && process.release.name === 'node';
20+
export const isNode: boolean =
21+
typeof process !== "undefined" &&
22+
process.release &&
23+
process.release.name === "node";
2124

2225
export class DDate extends Date {
23-
rfc3339TzOffset: string | undefined;
26+
originalDate: string | undefined;
2427
}
2528

26-
const RFC3339Re: RegExp = /^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2}):(\d{2})\.?(\d+)?(?:(?:([+-]\d{2}):?(\d{2}))|Z)?$/;
29+
const RFC3339Re =
30+
/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2}):(\d{2})\.?(\d+)?(?:(?:([+-]\d{2}):?(\d{2}))|Z)?$/;
2731
export function dateFromRFC3339String(date: string): DDate {
2832
const m = RFC3339Re.exec(date);
2933
if (m) {
30-
const _date = new DDate(date)
31-
if( m[8] === undefined && m[9] === undefined){
32-
_date.rfc3339TzOffset = 'Z'
33-
} else {
34-
_date.rfc3339TzOffset = `${m[8]}:${m[9]}`
35-
}
36-
37-
return _date
34+
const _date = new DDate(date);
35+
_date.originalDate = date;
36+
return _date;
3837
} else {
39-
throw new Error('unexpected date format: ' + date)
38+
throw new Error("unexpected date format: " + date);
4039
}
4140
}
4241

4342
export function dateToRFC3339String(date: Date | DDate): string {
44-
const offSetArr = getRFC3339TimezoneOffset(date).split(":")
45-
const tzHour = offSetArr.length == 1 ? 0 : +offSetArr[0];
46-
const tzMin = offSetArr.length == 1 ? 0 : +offSetArr[1];
47-
48-
const year = date.getFullYear() ;
49-
const month = date.getMonth();
50-
const day = date.getUTCDate();
51-
const hour = date.getUTCHours() + tzHour;
52-
const minute = date.getUTCMinutes() + tzMin;
53-
const second = date.getUTCSeconds();
54-
55-
let msec = date.getUTCMilliseconds().toString();
56-
msec = +msec === 0 ? "" : `.${pad(+msec, 3)}`
57-
58-
return year + "-" +
59-
pad(month + 1) + "-" +
60-
pad(day) + "T" +
61-
pad(hour) + ":" +
62-
pad(minute) + ":" +
63-
pad(second) +
64-
msec +
65-
offSetArr.join(":");
66-
}
67-
68-
// Helpers
69-
function pad(num: number, len: number = 2): string {
70-
let paddedNum = num.toString()
71-
if (paddedNum.length < len) {
72-
paddedNum = "0".repeat(len - paddedNum.length) + paddedNum
73-
} else if (paddedNum.length > len) {
74-
paddedNum = paddedNum.slice(0, len)
75-
}
76-
77-
return paddedNum
78-
}
79-
80-
function getRFC3339TimezoneOffset(date: Date | DDate): string {
81-
if (date instanceof DDate && date.rfc3339TzOffset) {
82-
return date.rfc3339TzOffset;
83-
}
84-
return "Z";
43+
if (date instanceof DDate && date.originalDate) {
44+
return date.originalDate;
45+
}
46+
return date.toISOString().split('.')[0] + "Z";
8547
}

packages/datadog-api-client-common/util.ts

Lines changed: 5 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const isNode: boolean =
2323
process.release.name === "node";
2424

2525
export class DDate extends Date {
26-
rfc3339TzOffset: string | undefined;
26+
originalDate: string | undefined;
2727
}
2828

2929
const RFC3339Re =
@@ -32,65 +32,16 @@ export function dateFromRFC3339String(date: string): DDate {
3232
const m = RFC3339Re.exec(date);
3333
if (m) {
3434
const _date = new DDate(date);
35-
if (m[8] === undefined && m[9] === undefined) {
36-
_date.rfc3339TzOffset = "Z";
37-
} else {
38-
_date.rfc3339TzOffset = `${m[8]}:${m[9]}`;
39-
}
40-
35+
_date.originalDate = date;
4136
return _date;
4237
} else {
4338
throw new Error("unexpected date format: " + date);
4439
}
4540
}
4641

4742
export function dateToRFC3339String(date: Date | DDate): string {
48-
const offSetArr = getRFC3339TimezoneOffset(date).split(":");
49-
const tzHour = offSetArr.length == 1 ? 0 : +offSetArr[0];
50-
const tzMin = offSetArr.length == 1 ? 0 : +offSetArr[1];
51-
52-
const year = date.getFullYear();
53-
const month = date.getMonth();
54-
const day = date.getUTCDate();
55-
const hour = date.getUTCHours() + tzHour;
56-
const minute = date.getUTCMinutes() + tzMin;
57-
const second = date.getUTCSeconds();
58-
59-
let msec = date.getUTCMilliseconds().toString();
60-
msec = +msec === 0 ? "" : `.${pad(+msec, 3)}`;
61-
62-
return (
63-
year +
64-
"-" +
65-
pad(month + 1) +
66-
"-" +
67-
pad(day) +
68-
"T" +
69-
pad(hour) +
70-
":" +
71-
pad(minute) +
72-
":" +
73-
pad(second) +
74-
msec +
75-
offSetArr.join(":")
76-
);
77-
}
78-
79-
// Helpers
80-
function pad(num: number, len = 2): string {
81-
let paddedNum = num.toString();
82-
if (paddedNum.length < len) {
83-
paddedNum = "0".repeat(len - paddedNum.length) + paddedNum;
84-
} else if (paddedNum.length > len) {
85-
paddedNum = paddedNum.slice(0, len);
86-
}
87-
88-
return paddedNum;
89-
}
90-
91-
function getRFC3339TimezoneOffset(date: Date | DDate): string {
92-
if (date instanceof DDate && date.rfc3339TzOffset) {
93-
return date.rfc3339TzOffset;
43+
if (date instanceof DDate && date.originalDate) {
44+
return date.originalDate;
9445
}
95-
return "Z";
46+
return date.toISOString().split(".")[0] + "Z";
9647
}

tests/api/date_time.test.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { MonthlyUsageAttributionResponse } from '../../packages/datadog-api-client-v1/models/MonthlyUsageAttributionResponse';
22
import { ObjectSerializer as ObjectSerializerV1 } from '../../packages/datadog-api-client-v1/models/ObjectSerializer';
3-
import { dateToRFC3339String } from "../../packages/datadog-api-client-common/util";
3+
import { dateFromRFC3339String, dateToRFC3339String } from "../../packages/datadog-api-client-common/util";
44

55
test('TestDeserializationOfInvalidDates', () => {
66
const data = `
@@ -51,3 +51,10 @@ test(`Test3339Dates`, () => {
5151
expect(result).toBe("2023-06-14T07:30:48Z");
5252
}
5353
);
54+
55+
test(`Test3339DatesWithTZ`, () => {
56+
const date = dateFromRFC3339String("2023-06-13T21:30:48-10:00");
57+
const result = dateToRFC3339String(date);
58+
expect(result).toBe("2023-06-13T21:30:48-10:00");
59+
}
60+
);

0 commit comments

Comments
 (0)