diff --git a/api/docs/tough-cookie.cookie.expirydate.md b/api/docs/tough-cookie.cookie.expirydate.md
new file mode 100644
index 00000000..2d32dfbf
--- /dev/null
+++ b/api/docs/tough-cookie.cookie.expirydate.md
@@ -0,0 +1,57 @@
+
+
+[Home](./index.md) > [tough-cookie](./tough-cookie.md) > [Cookie](./tough-cookie.cookie.md) > [expiryDate](./tough-cookie.cookie.expirydate.md)
+
+## Cookie.expiryDate() method
+
+Similar to [Cookie.expiryTime()](./tough-cookie.cookie.expirytime.md), computes the absolute unix-epoch milliseconds that this cookie expires and returns it as a Date.
+
+The "Max-Age" attribute takes precedence over "Expires" (as per the RFC). The [Cookie.lastAccessed](./tough-cookie.cookie.lastaccessed.md) attribute (or the `now` parameter if given) is used to offset the [Cookie.maxAge](./tough-cookie.cookie.maxage.md) attribute.
+
+If Expires ([Cookie.expires](./tough-cookie.cookie.expires.md)) is set, that's returned.
+
+**Signature:**
+
+```typescript
+expiryDate(now?: Date): Date | undefined;
+```
+
+## Parameters
+
+
+
+Parameter
+
+
+ |
+
+Type
+
+
+ |
+
+Description
+
+
+ |
+
+
+now
+
+
+ |
+
+Date
+
+
+ |
+
+_(Optional)_ can be used to provide a time offset (instead of [Cookie.lastAccessed](./tough-cookie.cookie.lastaccessed.md)) to use when calculating the "Max-Age" value
+
+
+ |
+
+**Returns:**
+
+Date \| undefined
+
diff --git a/api/docs/tough-cookie.cookie.md b/api/docs/tough-cookie.cookie.md
index fe5547fd..99f736f6 100644
--- a/api/docs/tough-cookie.cookie.md
+++ b/api/docs/tough-cookie.cookie.md
@@ -452,6 +452,24 @@ Does a deep clone of this cookie, implemented exactly as `Cookie.fromJSON(cookie
Encodes to a `Cookie` header value (specifically, the [Cookie.key](./tough-cookie.cookie.key.md) and [Cookie.value](./tough-cookie.cookie.value.md) properties joined with "=").
+
+
+
+[expiryDate(now)](./tough-cookie.cookie.expirydate.md)
+
+
+ |
+
+
+ |
+
+Similar to [Cookie.expiryTime()](./tough-cookie.cookie.expirytime.md), computes the absolute unix-epoch milliseconds that this cookie expires and returns it as a Date.
+
+The "Max-Age" attribute takes precedence over "Expires" (as per the RFC). The [Cookie.lastAccessed](./tough-cookie.cookie.lastaccessed.md) attribute (or the `now` parameter if given) is used to offset the [Cookie.maxAge](./tough-cookie.cookie.maxage.md) attribute.
+
+If Expires ([Cookie.expires](./tough-cookie.cookie.expires.md)) is set, that's returned.
+
+
|
diff --git a/api/tough-cookie.api.md b/api/tough-cookie.api.md
index a0409531..90e9e842 100644
--- a/api/tough-cookie.api.md
+++ b/api/tough-cookie.api.md
@@ -26,6 +26,7 @@ export class Cookie {
creationIndex: number;
domain: string | null;
expires: Date | 'Infinity' | null;
+ expiryDate(now?: Date): Date | undefined;
expiryTime(now?: Date): number | undefined;
extensions: string[] | null;
static fromJSON(str: unknown): Cookie | undefined;
diff --git a/lib/__tests__/cookieJar.spec.ts b/lib/__tests__/cookieJar.spec.ts
index 0f6c961d..0490a6f4 100644
--- a/lib/__tests__/cookieJar.spec.ts
+++ b/lib/__tests__/cookieJar.spec.ts
@@ -1227,6 +1227,7 @@ it('should fix issue #154 - Expiry should not be affected by creation date', asy
])
// the expiry time should be 60s from now (0)
expect(initialCookies[0]?.expiryTime()).toBe(now + 60 * 1000)
+ expect(initialCookies[0]?.expiryDate()).toEqual(new Date(now + 60 * 1000))
// advance the time by 1s, so now = 1000
jest.advanceTimersByTime(1000)
@@ -1247,6 +1248,9 @@ it('should fix issue #154 - Expiry should not be affected by creation date', asy
])
// the expiry time should be 60s from now (1000)
expect(updatedCookies[0]?.expiryTime()).toBe(now + 60 * 1000 + 1000)
+ expect(updatedCookies[0]?.expiryDate()).toEqual(
+ new Date(now + 60 * 1000 + 1000),
+ )
})
it('should fix issue #261 - URL objects should be accepted in setCookie', async () => {
diff --git a/lib/cookie/cookie.ts b/lib/cookie/cookie.ts
index 031fcf71..6724febf 100644
--- a/lib/cookie/cookie.ts
+++ b/lib/cookie/cookie.ts
@@ -856,6 +856,35 @@ export class Cookie {
return this.expires ? this.expires.getTime() : undefined
}
+ /**
+ * Similar to {@link Cookie.expiryTime}, computes the absolute unix-epoch milliseconds that this cookie expires and returns it as a Date.
+ *
+ * The "Max-Age" attribute takes precedence over "Expires" (as per the RFC). The {@link Cookie.lastAccessed} attribute
+ * (or the `now` parameter if given) is used to offset the {@link Cookie.maxAge} attribute.
+ *
+ * If Expires ({@link Cookie.expires}) is set, that's returned.
+ *
+ * @param now - can be used to provide a time offset (instead of {@link Cookie.lastAccessed}) to use when calculating the "Max-Age" value
+ */
+ expiryDate(now?: Date): Date | undefined {
+ const millisec = this.expiryTime(now)
+ if (millisec == Infinity) {
+ // The 31-bit value of 2147483647000 was chosen to be the MAX_TIME representable
+ // in tough-cookie though MDN states that the actual maximum value for a Date is 8.64e15.
+ // I'm guessing this is due to the Y2038 problem that would affect systems that store
+ // unix time as 32-bit integers.
+ // See:
+ // - https://github.com/salesforce/tough-cookie/commit/0616f70bf725e00c63d442544ad230c4f8b23357
+ // - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#the_epoch_timestamps_and_invalid_date
+ // - https://en.wikipedia.org/wiki/Year_2038_problem
+ return new Date(2147483647000)
+ } else if (millisec == -Infinity) {
+ return new Date(0)
+ } else {
+ return millisec == undefined ? undefined : new Date(millisec)
+ }
+ }
+
/**
* Indicates if the cookie has been persisted to a store or not.
* @public
|