Skip to content

Commit 21fd14c

Browse files
feat: add NepalTimezoneDate class and integrate with NepaliDate
1 parent 8a82798 commit 21fd14c

File tree

6 files changed

+501
-112
lines changed

6 files changed

+501
-112
lines changed

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,69 @@ console.log(date2.toString()) // 2080-03-23 10:15:00
223223
- `NepaliDate.minSupportedNepaliDate()`: Returns the minimum supported Nepali object.
224224
- `NepaliDate.maxSupportedNepaliDate()`: Returns the maximum supported Nepali object.
225225

226+
### NepalTimezoneDate
227+
228+
The `NepalTimezoneDate` class provides Gregorian date/time values in Nepal's timezone (Asia/Kathmandu, UTC+05:45).
229+
It works like JavaScript's `Date`, but always returns values as they would appear in Nepal, regardless of your system's timezone.
230+
It does **not** convert to the Nepali calendar.
231+
232+
#### Creating a NepalTimezoneDate object
233+
234+
You can create a `NepalTimezoneDate` object in several ways:
235+
236+
```javascript
237+
import { NepalTimezoneDate } from 'nepali-datetime'
238+
239+
// Current date/time in Nepal timezone
240+
const nowNepal = new NepalTimezoneDate()
241+
242+
// From a UTC date string
243+
const dateNepal = new NepalTimezoneDate('2024-12-28T15:00:35Z')
244+
245+
// From a JS Date object
246+
const jsDate = new Date('2024-12-28T15:00:35Z')
247+
const nepalDate = new NepalTimezoneDate(jsDate)
248+
249+
// From Nepal time components (year, month [0-based], date, hour, minute, second, ms)
250+
const npTzDate = new NepalTimezoneDate(2024, 11, 28, 20, 45, 35)
251+
```
252+
253+
#### Getting Nepal timezone date components
254+
255+
```javascript
256+
npTzDate.getYear() // 2024
257+
npTzDate.getMonth() // 11 (December, 0-based)
258+
npTzDate.getDate() // 28
259+
npTzDate.getHours() // 20
260+
npTzDate.getMinutes() // 45
261+
npTzDate.toString() // "2024-12-28 20:45:35 GMT+0545"
262+
npTzDate.toDate() // JS Date object in UTC
263+
```
264+
265+
#### Converting NepalTimezoneDate to NepaliDate
266+
267+
You can convert a `NepalTimezoneDate` object (Gregorian date in Nepal timezone) to a `NepaliDate` object:
268+
269+
```javascript
270+
const npTzDate = new NepalTimezoneDate('2024-12-28T15:00:35Z')
271+
const nepaliDate = new NepaliDate(npTzDate)
272+
console.log(nepaliDate.toString()) // e.g. 2081-09-12 20:45:35
273+
```
274+
275+
#### Comparing with JS Date
276+
277+
```javascript
278+
const systemDate = new Date('2024-12-28T15:00:35Z')
279+
const nepalDate = new NepalTimezoneDate('2024-12-28T15:00:35Z')
280+
281+
// System Date (depends on your computer's timezone)
282+
console.log(systemDate.getHours()) // e.g. 10 (US), 16 (EU), 20 (Nepal)
283+
284+
// NepalTimezoneDate (always Nepal time)
285+
console.log(nepalDate.getHours()) // 20
286+
console.log(nepalDate.toString()) // "2024-12-28 20:45:35 GMT+0545"
287+
```
288+
226289
### dateConverter
227290

228291
The `dateConverter` module provides core functions for converting dates between the Nepali and English calendars.

src/NepalTimezoneDate.ts

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
import {
2+
OLD_UTC_OFFSET_IN_MS,
3+
TIMEZONE_TRANSITION_DATE_REFERENCE,
4+
TIMEZONE_TRANSITION_TIMESTAMP,
5+
UTC_OFFSET_IN_MS,
6+
} from './constants'
7+
8+
/**
9+
* Represents a Gregorian date/time in Nepal's timezone (Asia/Kathmandu, UTC+05:45).
10+
* Behaves like a JavaScript `Date` object, with all getters returning values in Nepal's timezone.
11+
* Does not convert to the Nepali (Bikram Sambat) calendar.
12+
*
13+
* @example
14+
* const date = new NepalTimezoneDate();
15+
* or,
16+
* const date = new NepalTimezoneDate(2024, 11, 28, 20, 45, 35) // 20:45 is Nepal time
17+
* date.toString() // "2024-12-28 20:45:35 GMT+0545"
18+
* date.toDate() // JS Date object in UTC
19+
*
20+
* @example
21+
* const date = new NepalTimezoneDate(new Date())
22+
* date.getYear() // Nepal year
23+
* date.getMinutes() // Nepal minutes
24+
*/
25+
class NepalTimezoneDate {
26+
private _date: Date
27+
private _nepalTimezoneSafeDate: {
28+
year: number
29+
month0: number
30+
day: number
31+
hour: number
32+
minute: number
33+
second: number
34+
ms: number
35+
weekDay: number
36+
}
37+
38+
/**
39+
* Get the Nepali date and time components (Gregorian calendar) from a given date.
40+
* The input can be any date from any timezone, it is converted into the Nepal's timezone (Asia/Kathmandu).
41+
*
42+
* @param date - The input date for which to retrieve the Nepali date and time.
43+
* @returns An object containing the Nepali date and time components.
44+
*/
45+
private static getNepalDateAndTime(date: Date) {
46+
const time = date.getTime()
47+
48+
// Handling the timezone switch froqm GMT+5:30 to GMT+5:45
49+
// In javascript the switched time is
50+
// 504901800000: Wed Jan 01 1986 00:15:00 GMT+0545 (Nepal Time) : Adjusted time
51+
const utcOffsetInMs =
52+
time < TIMEZONE_TRANSITION_TIMESTAMP
53+
? OLD_UTC_OFFSET_IN_MS
54+
: UTC_OFFSET_IN_MS
55+
56+
// Calculate the Nepali reference date by adding the offset to the input date's unix timestamp
57+
const nepaliRefDate = new Date(time + utcOffsetInMs)
58+
59+
// Extract the Nepali date and time components
60+
const npYear = nepaliRefDate.getUTCFullYear()
61+
const npMonth0 = nepaliRefDate.getUTCMonth()
62+
const npDay = nepaliRefDate.getUTCDate()
63+
const npHour = nepaliRefDate.getUTCHours()
64+
const npMinutes = nepaliRefDate.getUTCMinutes()
65+
const npSeconds = nepaliRefDate.getUTCSeconds()
66+
const npMs = nepaliRefDate.getUTCMilliseconds()
67+
const npWeekDay = nepaliRefDate.getUTCDay()
68+
69+
// Return the Nepali date and time components as an object
70+
return {
71+
year: npYear,
72+
month0: npMonth0,
73+
day: npDay,
74+
hour: npHour,
75+
minute: npMinutes,
76+
second: npSeconds,
77+
ms: npMs,
78+
weekDay: npWeekDay,
79+
}
80+
}
81+
82+
/**
83+
* Get the Date object from the given Nepali date and time components.
84+
*
85+
* @param year - The year component of the Nepali date.
86+
* @param month0 - The month component of the Nepali date (1-12).
87+
* @param date - The day component of the Nepali date.
88+
* @param hour - The hour component of the Nepali time.
89+
* @param minute - The minute component of the Nepali time.
90+
* @param second - The second component of the Nepali time.
91+
* @param ms - The millisecond component of the Nepali time.
92+
* @returns A `Date` object representing the UTC date and time.
93+
*/
94+
private static getDate(
95+
year: number,
96+
month: number,
97+
day: number,
98+
hour: number,
99+
minute: number,
100+
second: number,
101+
ms: number
102+
): Date {
103+
// Create a new Date object using the given Nepali date and time parameters
104+
const nepaliRefDate = new Date(year, month, day, hour, minute, second, ms)
105+
106+
let utcOffsetInMs =
107+
nepaliRefDate < TIMEZONE_TRANSITION_DATE_REFERENCE
108+
? OLD_UTC_OFFSET_IN_MS
109+
: UTC_OFFSET_IN_MS
110+
111+
// Getting current timezone offset (in milliseconds)
112+
const currentOffsetInMS = -1 * nepaliRefDate.getTimezoneOffset() * 60 * 1000
113+
114+
// Subtracting Nepali ref date by Nepali timezone offset and current timezone Offset
115+
const date = new Date(
116+
nepaliRefDate.getTime() - utcOffsetInMs + currentOffsetInMS
117+
)
118+
119+
// Return the date object
120+
return date
121+
}
122+
123+
/**
124+
* Creates a NepalTimezoneDate instance for Asia/Kathmandu timezone (UTC+05:45).
125+
* Accepts:
126+
* - No arguments (current date/time)
127+
* - Unix epoch (number)
128+
* - Date object
129+
* - year, month, ... (Nepal timezone components)
130+
*/
131+
constructor(...args: any[]) {
132+
if (args.length === 0) {
133+
// no arguments - current date/time
134+
this._date = new Date()
135+
} else if (args.length === 1 && typeof args[0] === 'number') {
136+
// Unix epoch (ms)
137+
this._date = new Date(args[0])
138+
} else if (args.length === 1 && args[0] instanceof Date) {
139+
// Date object
140+
this._date = new Date(args[0])
141+
} else if (
142+
args.length >= 2 &&
143+
args.length <= 7 &&
144+
args.every(arg => typeof arg === 'number')
145+
) {
146+
// year, month, day, hour, minute, second, ms (Nepal timezone components)
147+
const [year, month, day, hour = 0, minute = 0, second = 0, ms = 0] = args
148+
this._date = NepalTimezoneDate.getDate(
149+
year,
150+
month,
151+
day,
152+
hour,
153+
minute,
154+
second,
155+
ms
156+
)
157+
} else {
158+
throw new Error('Invalid arguments for NepalTimezoneDate')
159+
}
160+
this._nepalTimezoneSafeDate = NepalTimezoneDate.getNepalDateAndTime(this._date)
161+
}
162+
163+
/**
164+
* Retrieves the year in Nepal's timezone (Gregorian calendar).
165+
* @returns {number} The full numeric value representing the year
166+
*/
167+
getYear(): number {
168+
return this._nepalTimezoneSafeDate.year
169+
}
170+
171+
/**
172+
* Retrieves the month in Nepal's timezone (Gregorian calendar).
173+
* @returns {number} The numeric value representing the month
174+
*/
175+
getMonth(): number {
176+
return this._nepalTimezoneSafeDate.month0
177+
}
178+
179+
/**
180+
* Retrieves the day of the month in Nepal's timezone (Gregorian calendar).
181+
* @returns {number} The numeric value representing the day of the month.
182+
*/
183+
getDate(): number {
184+
return this._nepalTimezoneSafeDate.day
185+
}
186+
187+
/**
188+
* Retrieves the hour in Nepal's timezone.
189+
* @returns {number} The numeric value representing the hour
190+
*/
191+
getHours(): number {
192+
return this._nepalTimezoneSafeDate.hour
193+
}
194+
195+
/**
196+
* Retrieves the minute in Nepal's timezone.
197+
* @returns {number} The numeric value representing the minute
198+
*/
199+
getMinutes(): number {
200+
return this._nepalTimezoneSafeDate.minute
201+
}
202+
203+
/**
204+
* Retrieves the second in Nepal's timezone.
205+
* @returns {number} The numeric value representing the second
206+
*/
207+
getSeconds(): number {
208+
return this._nepalTimezoneSafeDate.second
209+
}
210+
211+
/**
212+
* Retrieves the millisecond in Nepal's timezone.
213+
* @returns {number} The numeric value representing the millisecond
214+
*/
215+
getMilliseconds(): number {
216+
return this._nepalTimezoneSafeDate.ms
217+
}
218+
219+
/**
220+
* Retrieves the day of the week in Nepal's timezone.
221+
* @returns {number} The numeric value representing the day of the week
222+
*/
223+
getDay(): number {
224+
return this._nepalTimezoneSafeDate.weekDay
225+
}
226+
227+
/**
228+
* Retrieves the Unix timestamp (in milliseconds) of the date.
229+
* @returns {number} The numeric value representing the time in milliseconds.
230+
*/
231+
getTime(): number {
232+
return this._date.getTime()
233+
}
234+
235+
/**
236+
* Returns a string representation of the NepalTimezoneDate object in Nepal's timezone.
237+
* @returns {string} The string representation in the format "YYYY-MM-DD HH:mm:ss GMT+0545".
238+
*/
239+
toString(): string {
240+
const np = this._nepalTimezoneSafeDate
241+
return (
242+
`${np.year}-${String(np.month0 + 1).padStart(2, '0')}-${String(np.day).padStart(2, '0')} ` +
243+
`${String(np.hour).padStart(2, '0')}:${String(np.minute).padStart(2, '0')}:${String(np.second).padStart(2, '0')} GMT+0545`
244+
)
245+
}
246+
247+
/**
248+
* Returns the underlying Date object (UTC).
249+
* @returns {Date} The equivalent JavaScript Date object.
250+
*/
251+
toDate(): Date {
252+
return new Date(this._date)
253+
}
254+
}
255+
256+
export default NepalTimezoneDate

0 commit comments

Comments
 (0)