startAtOperationTime and db.collection.watch()

To whom it may concern,

I’m trying to start getting changes from change streams given a date/time. There’s a handy parameter to “db.collection.watch()”, startAtOperationTime, that, in theory one could you to specify the date/time. One would think that one could extract a timestamp from a date. Heck, in a perfect world, one would provide the Date or ISODate as the “startAtOperationTime” value and it would just work. Nope, no auto coercion; this parameter value must be a Timestamp. It doesn’t help that there are multiple definitions of what a timestamp is.

Unfortunately, it is difficult to convert Date/IOSDate. You can’t simply use the output of $toLong aggregation operator. By the way, you could create a Date using that long, but curiously, not a ISODate. The “watch” operation wants a “timestamp” and complains if it gets something that isn’t one of those.

I attempted to step through the conversion using an aggregation pipeline

$ db.copyProgress.aggregate([
...   {$match:{"_id": "csTestCopy"}},
...   {
...      "$project":{
...         "_id":0,
...         "startedEpoch":{
...            "$toLong":"$started"
...         }
...      }
...   },
...   {
...     "$project":
...     {
...      "startedTimeSeconds":
...       {
...         "$trunc": {
...           $divide: [ "$startedEpoch", 100000 ]
...         }
...       }
...     }
...   },
...   {
...      "$project":{
...         "startedTimestamp": new Timestamp( 1,
...           { "$toInt":"$startedTimeSeconds" }
...         )
...      }
...   }
... ])
2020-04-08T14:14:33.996-0500 E  QUERY    [js] Error: Timestamp increment must be a number :
@(shell):24:29

I added in the “$toInt” conversion hoping to get around this error, but this error goes deep.

So, what is the magic to have a Date/time and convert that into a Timestamp that “watch()” wants?

Regards,
Steve

Does this help?