Repository: googlemaps/google-maps-services-js (ts)

Issue:
Directions: using "now" as departure time gets parsed as NaN instead of "now" on the query params
#### Environment details

OS: linux (docker image: node:12.12.0-alpine)
Library version: `2.3.0` but looking at the code in master seems that still happens latest releases

#### Steps to reproduce

1. create a request for the directions API
1. set the `departure_time` param as `"now"`

#### Code example

```ts
const { data: directions } = await this.mapsClient.directions({
  key: "some key",
  origin: {
    lng: fromAddress.location.coordinates[0],
    lat: fromAddress.location.coordinates[1],
  },
  destination: {
    lng: toAddress.location.coordinates[0],
    lat: toAddress.location.coordinates[1],
  },
  departure_time: "now",
});
```

#### Stack trace
```
Error: Request failed with status code 400
  File "/app/node_modules/axios/lib/core/createError.js", line 16, col 15, in createError
    var error = new Error(message);
  File "/app/node_modules/axios/lib/core/settle.js", line 17, col 12, in settle
    reject(createError(
  File "/app/node_modules/axios/lib/adapters/http.js", line 236, col 11, in Unzip.handleStreamEnd
    settle(resolve, reject, response);
  File "events.js", line 215, col 7, in Unzip.emit
  File "domain.js", line 476, col 20, in Unzip.EventEmitter.emit
  File "_stream_readable.js", line 1183, col 12, in endReadableNT
  File "internal/process/task_queues.js", line 80, col 21, in processTicksAndRejections
```

#### Generated url
`https://maps.googleapis.com/maps/api/directions/json?departure_time=NaN...`


Pull request description:
fix: support serializing now
closes #423 

Patch:
diff --git a/src/serialize.ts b/src/serialize.ts
index 883b987f0..b0a9a1381 100644
--- a/src/serialize.ts
+++ b/src/serialize.ts
@@ -35,7 +35,7 @@ export function latLngToString(o: LatLng) {
   }
 
   return o
-    .map(x => {
+    .map((x) => {
       return x.toString();
     })
     .join(",");
@@ -47,7 +47,7 @@ export function objectToString(o: string | object): string {
   } else {
     let keys = Object.keys(o);
     keys.sort();
-    return keys.map(k => k + ":" + o[k]).join(separator);
+    return keys.map((k) => k + ":" + o[k]).join(separator);
   }
 }
 
@@ -101,7 +101,7 @@ export function serializer(
   format: serializerFormat,
   queryStringOptions: object = {
     arrayFormat: "separator",
-    arrayFormatSeparator: separator
+    arrayFormatSeparator: separator,
   }
 ) {
   return (params: { [key: string]: any }) => {
@@ -114,9 +114,12 @@ export function serializer(
   };
 }
 
-export function toTimestamp(o: number | Date) {
+export function toTimestamp(o: "now" | number | Date): number | "now" {
+  if (o === "now") {
+    return o;
+  }
   if (o instanceof Date) {
     return Number(o) / 1000;
   }
-  return o
+  return o;
 }


Test patch:
diff --git a/e2e/directions.test.ts b/e2e/directions.test.ts
index 0311e7928..33000287c 100644
--- a/e2e/directions.test.ts
+++ b/e2e/directions.test.ts
@@ -29,12 +29,11 @@ test("directions should get correct result", async () => {
       "McLaren+Vale,SA",
     ],
     optimize: true,
+    departure_time: "now" as const,
     key: process.env.GOOGLE_MAPS_API_KEY,
   };
   const r = await directions({ params: params });
-  expect(r.request.path).toMatch(
-    "waypoints=optimize%3Atrue|Barossa"
-  );
+  expect(r.request.path).toMatch("waypoints=optimize%3Atrue|Barossa");
   expect(r.data.status).toEqual(Status.OK);
   expect(r.data.routes[0].legs[0].distance.value).toBeGreaterThan(0);
   expect(
diff --git a/src/serialize.test.ts b/src/serialize.test.ts
index 2c7869176..5832f47fa 100644
--- a/src/serialize.test.ts
+++ b/src/serialize.test.ts
@@ -22,7 +22,7 @@ import {
   objectToString,
   serializer,
   toLatLngLiteral,
-  toTimestamp
+  toTimestamp,
 } from "./serialize";
 
 test("latLngToString is correct", () => {
@@ -41,22 +41,22 @@ test("latLngBoundsToString is correct", () => {
   expect(
     latLngBoundsToString({
       southwest: { lat: 1, lng: 2 },
-      northeast: { lat: 3, lng: 4 }
+      northeast: { lat: 3, lng: 4 },
     })
   ).toBe("1,2|3,4");
 });
 
 test("serializer", () => {
-  expect(serializer({ quz: o => o })({ foo: ["bar"] })).toBe("foo=bar");
+  expect(serializer({ quz: (o) => o })({ foo: ["bar"] })).toBe("foo=bar");
   expect(
-    serializer({ foo: o => o.map((latLng: LatLng) => latLngToString(latLng)) })(
-      {
-        foo: [
-          [0, 1],
-          [2, 3]
-        ]
-      }
-    )
+    serializer({
+      foo: (o) => o.map((latLng: LatLng) => latLngToString(latLng)),
+    })({
+      foo: [
+        [0, 1],
+        [2, 3],
+      ],
+    })
   ).toBe("foo=0%2C1|2%2C3");
 });
 
@@ -75,7 +75,7 @@ test("latLngArrayToStringMaybeEncoded", () => {
   expect(
     latLngArrayToStringMaybeEncoded([
       [40.714728, -73.998672],
-      [-34.397, 150.644]
+      [-34.397, 150.644],
     ])
   ).toEqual("enc:abowFtzsbMhgmiMuobzi@");
 });
@@ -85,11 +85,11 @@ test("toLatLngLiteral", () => {
   expect(toLatLngLiteral([0, 1])).toEqual({ lat: 0, lng: 1 });
   expect(toLatLngLiteral({ lat: 0, lng: 1 })).toEqual({
     lat: 0,
-    lng: 1
+    lng: 1,
   });
   expect(toLatLngLiteral({ latitude: 0, longitude: 1 })).toEqual({
     lat: 0,
-    lng: 1
+    lng: 1,
   });
   expect(() => {
     toLatLngLiteral({} as LatLngLiteral);
@@ -98,10 +98,9 @@ test("toLatLngLiteral", () => {
 
 test("toTimestamp", () => {
   expect(toTimestamp(100)).toEqual(100);
-  
+
   const dt = new Date();
-  const seconds = Number(dt) / 1000
+  const seconds = Number(dt) / 1000;
   expect(toTimestamp(dt)).toEqual(seconds);
-
+  expect(toTimestamp("now")).toEqual("now");
 });
-