Skip to content

Commit f0f5fd2

Browse files
authored
feat: add fromDate and fromTimestamp factory methods to DateTime (#654)
1 parent daf741a commit f0f5fd2

File tree

2 files changed

+170
-1
lines changed

2 files changed

+170
-1
lines changed

src/datetime.ts

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,65 @@ export class DateTime<T extends Time | undefined> {
247247
return DateTime.create(year, month, day, hour, minute, second, true);
248248
}
249249

250+
/**
251+
* Creates a new UTC DateTime object from a JavaScript Date object.
252+
*
253+
* The resulting DateTime will have `utc` set to `true` and will represent
254+
* the same moment in time as the input Date object.
255+
*
256+
* @param date - A JavaScript Date object
257+
* @returns A DateTime instance with UTC time
258+
*
259+
* @example
260+
* ```typescript
261+
* const jsDate = new Date('2024-01-15T14:30:00.000Z');
262+
* const datetime = DateTime.fromDate(jsDate);
263+
* console.log(datetime.year); // 2024
264+
* console.log(datetime.month); // 1
265+
* console.log(datetime.day); // 15
266+
* console.log(datetime.time.hour); // 14
267+
* console.log(datetime.time.minute); // 30
268+
* console.log(datetime.time.second); // 0
269+
* console.log(datetime.time.utc); // true
270+
* ```
271+
*/
272+
public static fromDate(date: Date): DateTime<Time> {
273+
return DateTime.utc(
274+
date.getUTCFullYear(),
275+
date.getUTCMonth() + 1,
276+
date.getUTCDate(),
277+
date.getUTCHours(),
278+
date.getUTCMinutes(),
279+
date.getUTCSeconds(),
280+
);
281+
}
282+
283+
/**
284+
* Creates a new UTC DateTime object from a Unix timestamp in milliseconds.
285+
*
286+
* The resulting DateTime will have `utc` set to `true` and will represent
287+
* the moment in time corresponding to the given timestamp.
288+
*
289+
* @param timestamp - Unix timestamp in milliseconds since January 1, 1970 00:00:00 UTC
290+
* @returns A DateTime instance with UTC time
291+
*
292+
* @example
293+
* ```typescript
294+
* const timestamp = Date.UTC(2024, 0, 15, 14, 30, 0); // 1705329000000
295+
* const datetime = DateTime.fromTimestamp(timestamp);
296+
* console.log(datetime.year); // 2024
297+
* console.log(datetime.month); // 1
298+
* console.log(datetime.day); // 15
299+
* console.log(datetime.time.hour); // 14
300+
* console.log(datetime.time.minute); // 30
301+
* console.log(datetime.time.second); // 0
302+
* console.log(datetime.time.utc); // true
303+
* ```
304+
*/
305+
public static fromTimestamp(timestamp: number): DateTime<Time> {
306+
return DateTime.fromDate(new Date(timestamp));
307+
}
308+
250309
/**
251310
* Creates a new DateTime object from a plain object representation.
252311
*
@@ -310,7 +369,6 @@ export class DateTime<T extends Time | undefined> {
310369
* const utc = DateTime.fromString("20240115T143000Z");
311370
* ```
312371
*/
313-
// TODO: add template expression
314372
public static fromString(str: string): DateTime<Time> | DateTime<undefined> {
315373
if (!(str.length === 8 || (str.length <= 16 && str.length >= 15))) {
316374
throw new TypeError('Invalid date time string');

tests/unit/datetime.spec.ts

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,117 @@ describe(DateTime, () => {
110110
});
111111
});
112112

113+
describe('fromDate', () => {
114+
it.each([
115+
{
116+
year: 2024,
117+
month: 1,
118+
day: 15,
119+
hour: 14,
120+
minute: 30,
121+
second: 0,
122+
},
123+
{
124+
year: 2005,
125+
month: 9,
126+
day: 4,
127+
hour: 9,
128+
minute: 1,
129+
second: 2,
130+
},
131+
{
132+
year: 1970,
133+
month: 1,
134+
day: 1,
135+
hour: 0,
136+
minute: 0,
137+
second: 0,
138+
},
139+
])(
140+
'should create UTC datetime from Date $input',
141+
({ year, month, day, hour, minute, second }) => {
142+
const datetime = DateTime.fromDate(
143+
new Date(Date.UTC(year, month - 1, day, hour, minute, second)),
144+
);
145+
146+
expect(datetime.year).toBe(year);
147+
expect(datetime.month).toBe(month);
148+
expect(datetime.day).toBe(day);
149+
expect(datetime.time.hour).toBe(hour);
150+
expect(datetime.time.minute).toBe(minute);
151+
expect(datetime.time.second).toBe(second);
152+
expect(datetime.time.utc).toBe(true);
153+
},
154+
);
155+
156+
it('should be convertible back to Date', () => {
157+
const originalDate = new Date(Date.UTC(2024, 5, 20, 10, 30, 45));
158+
const datetime = DateTime.fromDate(originalDate);
159+
const convertedDate = datetime.toDate();
160+
161+
expect(convertedDate.getTime()).toBe(originalDate.getTime());
162+
});
163+
});
164+
165+
describe('fromTimestamp', () => {
166+
it.each([
167+
{
168+
timestamp: Date.UTC(2024, 0, 15, 14, 30, 0),
169+
expected: {
170+
year: 2024,
171+
month: 1,
172+
day: 15,
173+
hour: 14,
174+
minute: 30,
175+
second: 0,
176+
},
177+
},
178+
{
179+
timestamp: Date.UTC(2005, 8, 4, 9, 1, 2),
180+
expected: {
181+
year: 2005,
182+
month: 9,
183+
day: 4,
184+
hour: 9,
185+
minute: 1,
186+
second: 2,
187+
},
188+
},
189+
{
190+
timestamp: 0,
191+
expected: {
192+
year: 1970,
193+
month: 1,
194+
day: 1,
195+
hour: 0,
196+
minute: 0,
197+
second: 0,
198+
},
199+
},
200+
])(
201+
'should create UTC datetime from timestamp $input',
202+
({ timestamp, expected }) => {
203+
const datetime = DateTime.fromTimestamp(timestamp);
204+
205+
expect(datetime.year).toBe(expected.year);
206+
expect(datetime.month).toBe(expected.month);
207+
expect(datetime.day).toBe(expected.day);
208+
expect(datetime.time.hour).toBe(expected.hour);
209+
expect(datetime.time.minute).toBe(expected.minute);
210+
expect(datetime.time.second).toBe(expected.second);
211+
expect(datetime.time.utc).toBe(true);
212+
},
213+
);
214+
215+
it('should be convertible back to timestamp', () => {
216+
const originalTimestamp = Date.UTC(2024, 5, 20, 10, 30, 45);
217+
const datetime = DateTime.fromTimestamp(originalTimestamp);
218+
const convertedTimestamp = datetime.toTimestamp();
219+
220+
expect(convertedTimestamp).toBe(originalTimestamp);
221+
});
222+
});
223+
113224
describe('fromPlain', () => {
114225
it.each([
115226
{

0 commit comments

Comments
 (0)