<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Alan Storm</title>
    <description>The latest articles on Forem by Alan Storm (@astorm).</description>
    <link>https://forem.com/astorm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F356868%2Fc221172d-d9fd-4138-9cf3-bb1aa8903e11.jpeg</url>
      <title>Forem: Alan Storm</title>
      <link>https://forem.com/astorm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/astorm"/>
    <language>en</language>
    <item>
      <title>Javascript Date String Parsing</title>
      <dc:creator>Alan Storm</dc:creator>
      <pubDate>Thu, 29 Apr 2021 20:01:00 +0000</pubDate>
      <link>https://forem.com/astorm/javascript-date-string-parsing-3c8d</link>
      <guid>https://forem.com/astorm/javascript-date-string-parsing-3c8d</guid>
      <description>&lt;p&gt;One of my favorite features of PHP is &lt;a href="https://www.php.net/strtotime"&gt;the &lt;code&gt;strtotime&lt;/code&gt; function&lt;/a&gt;.  This function lets you pass in a date string and have a unix timestamp returned&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;strtotime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'2021-04-01'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$time&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// outputs&lt;/span&gt;
    &lt;span class="c1"&gt;// 2021-04-01T00:00:00-07:00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What's great about it is it works with a variety of date formats.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;strtotime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'04/01/2021'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$time&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// outputs&lt;/span&gt;
    &lt;span class="c1"&gt;// 2021-04-01T00:00:00-07:00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And don't worry -- if you're all objects all the time the same string parsing behavior works with PHP's &lt;code&gt;DateTime&lt;/code&gt; class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'April 1, 2020'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$date&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// outputs&lt;/span&gt;
    &lt;span class="c1"&gt;// 2020-04-01T00:00:00-07:00&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With &lt;code&gt;strtotime&lt;/code&gt; if you're working with sketchy data (in other words -- real data) you have a bit more confidence that your code will keep working when/if your code encounters an unexpected date format.&lt;/p&gt;

&lt;h2&gt;
  
  
  Javascript's Date.parse
&lt;/h2&gt;

&lt;p&gt;Javascript has similar functionality built in to its &lt;code&gt;Date&lt;/code&gt; object.  Unfortunately, there's a few weird edge cases around timezones that make it unreliable. The following examples all use a Node.js 14.2 REPL, but should apply generally to modern versions of javascript.&lt;/p&gt;

&lt;p&gt;In javascript, you can use the &lt;code&gt;Date.parse&lt;/code&gt; method to automatically parse a date string and get a unix timestamp back, or you can pass a string directly to the &lt;code&gt;Date&lt;/code&gt; object's constructor function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;$&lt;/span&gt; &lt;span class="nx"&gt;node&lt;/span&gt;
    &lt;span class="nx"&gt;Welcome&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;Node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt; &lt;span class="nx"&gt;v14&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;Type&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.help&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;more&lt;/span&gt; &lt;span class="nx"&gt;information&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;April 1, 2021&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="mi"&gt;1617260400000&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;April 1, 2021&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="nx"&gt;T07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.000&lt;/span&gt;&lt;span class="nx"&gt;Z&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Right away we see a few small differences from &lt;code&gt;strtotime&lt;/code&gt;.  First, javascript reports its unix epoch timestamps in milliseconds, not seconds.  Second, javascript's ISO date formatting (the &lt;code&gt;'c'&lt;/code&gt; format in PHP's &lt;code&gt;stringToTime&lt;/code&gt;) always reports using UTC time (indicated by the trailing &lt;code&gt;Z&lt;/code&gt;), where PHP reports the timezone offset &lt;em&gt;from&lt;/em&gt; UTC.  So these two ISO date strings&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2021-04-01T00:00:00-07:00
2021-04-01T07:00:00.000Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;represent the same time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: All example in this article were run on a computer setup for US West Coast time during daylight savings time -- you may see an offset other than seven hours depending on when and where you run the code samples.&lt;/p&gt;

&lt;p&gt;So far these are important, but small, differences. The bigger difference comes when you start using date strings that look like they're part of an &lt;a href="https://en.wikipedia.org/wiki/ISO_8601"&gt;ISO 8601 date string&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-04-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="nx"&gt;T00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.000&lt;/span&gt;&lt;span class="nx"&gt;Z&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see that, like before, javascript's using a &lt;code&gt;Z&lt;/code&gt; to indicate the date is in UTC time.  However, you'll also notice the time is &lt;em&gt;not&lt;/em&gt; &lt;code&gt;07:00:00&lt;/code&gt; -- it's &lt;code&gt;00:00:00&lt;/code&gt;.  In our previous examples javascript assumes a time of midnight using the &lt;em&gt;current&lt;/em&gt; configured timezone.  However, when we used  &lt;code&gt;2021-04-01&lt;/code&gt; as a date string, javascript assumed a time of midnight with a UTC timezone.  Because &lt;code&gt;2021-04-01&lt;/code&gt; looks like an incomplete ISO 8601 date, javascript assumed it &lt;em&gt;was&lt;/em&gt; an ISO 8601 date with a missing timezone, and the timezone defaulted to UTC.&lt;/p&gt;

&lt;p&gt;If you're not aware of it, this behavior can cause bugs in your program.  I ran into this when I was processing some CSV files from banks.  Some transactions appeared on the wrong day because one CSV files used &lt;code&gt;YYYY-MM-DD&lt;/code&gt; format and another used the &lt;code&gt;MM/DD/YYYY&lt;/code&gt; format.  &lt;/p&gt;

&lt;p&gt;This isn't the only problem with string parsing in the &lt;code&gt;Date&lt;/code&gt; class. The MDN documentation on javascript's &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#date_time_string_format"&gt;Date Time String Format&lt;/a&gt; covers some other edge cases you might be interested in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Date Libraries
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Date&lt;/code&gt; object is one of javascript's original objects, and its behavior is not likely to change.  If some javascript vendor "fixed" this to be more consistent, it would almost certainly break a large amount of code in the world.  Because of this, most javascript programmers rely on a third party library to handle dates.&lt;/p&gt;

&lt;p&gt;Let's look at four popular date handling libraries (&lt;code&gt;date-fns&lt;/code&gt;, &lt;code&gt;dayjs&lt;/code&gt;, &lt;code&gt;luxon&lt;/code&gt;, and &lt;code&gt;moment&lt;/code&gt;) and see how they handle &lt;code&gt;YYYY-MM-DD&lt;/code&gt; case.  The following examples presume you have these date libraries installed via npm.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ npm install date-fns dayjs luxon moment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Moment
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://momentjs.com/"&gt;moment&lt;/a&gt; library is one of the most popular date libraries for javascript, even if its developers have stepped away from it and consider it "finished".  Let's see how it handles abbreviated ISO date strings.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;moment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-04-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;Moment&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="nx"&gt;T00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Success!  Unlike the native &lt;code&gt;Date&lt;/code&gt; object, moment doesn't assume a UTC timezone.  Instead, it assumes the currently configured system timezone.&lt;/p&gt;

&lt;p&gt;However, something interesting will happen if we try to parse a date string that's not ISO formatted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;04/01/2021&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;Deprecation&lt;/span&gt; &lt;span class="nx"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="nx"&gt;provided&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;recognized&lt;/span&gt; &lt;span class="nx"&gt;RFC2822&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt;
    &lt;span class="nx"&gt;ISO&lt;/span&gt; &lt;span class="nx"&gt;format&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;moment&lt;/span&gt; &lt;span class="nx"&gt;construction&lt;/span&gt; &lt;span class="nx"&gt;falls&lt;/span&gt; &lt;span class="nx"&gt;back&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;js&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;which&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt;
    &lt;span class="nx"&gt;reliable&lt;/span&gt; &lt;span class="nx"&gt;across&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;browsers&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;versions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Non&lt;/span&gt; &lt;span class="nx"&gt;RFC2822&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;ISO&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="nx"&gt;formats&lt;/span&gt;
    &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;discouraged&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

    &lt;span class="nx"&gt;Please&lt;/span&gt; &lt;span class="nx"&gt;refer&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//momentjs.com/guides/#/warnings/js-date/ for more info.&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
    &lt;span class="nx"&gt;Moment&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="nx"&gt;T00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;moment&lt;/code&gt; function still returns a date, but we get a warning that our date's in a format that moment doesn't recognize, and that moment is falling back to using javascript s built in &lt;code&gt;Date&lt;/code&gt;. So, although we got the answer we wanted for our ISO 8601 date (&lt;code&gt;Moment&amp;lt;2021-04-01T00:00:00-07:00&amp;gt;&lt;/code&gt;), we might not be so lucky if we were using a different version of javascript or a  string format that wasn't ISO 8601 based.&lt;/p&gt;

&lt;h3&gt;
  
  
  Luxon
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://moment.github.io/luxon/"&gt;luxon&lt;/a&gt; date library, (&lt;a href="https://moment.github.io/luxon/docs/manual/why.html"&gt;created by one of the maintainers of moment&lt;/a&gt; ) has an different approach.&lt;/p&gt;

&lt;p&gt;Luxon can handle &lt;a href="https://moment.github.io/luxon/docs/manual/parsing.html"&gt;a variety of date formats&lt;/a&gt;, but does not attempt to automatically detect which format is which.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;luxon&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromISO&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
    &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromRFC2822&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
    &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromSQL&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
    &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromMillis&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
    &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromSeconds&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
    &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromJsDate&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luxon's philosophy is that it's up to you, the end-user-programmer, to know what sort of dates you're dealing with.  If you call one of these methods with an invalid date format, luxon will return a &lt;code&gt;DateTime&lt;/code&gt; object, but that object will be considered invalid&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromISO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;04/01/2021&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;DateTime&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
      &lt;span class="nl"&gt;invalid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Invalid&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;reason&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;unparsable&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;explanation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`the input "04/01/2021" can't be parsed as ISO 8601`&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Day.js
&lt;/h3&gt;

&lt;p&gt;Next up &lt;a href="https://day.js.org/"&gt;is Day.js&lt;/a&gt;, a library that prides itself its small size and a Moment.js like API.&lt;/p&gt;

&lt;p&gt;Day.js &lt;em&gt;seems&lt;/em&gt; capable of parsing a variety of date formats, and doesn't get caught up in the ISO 8601 UTC issue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dayjs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dayjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kc"&gt;undefined&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-04-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="nx"&gt;T07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.000&lt;/span&gt;&lt;span class="nx"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4/01/2021&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="nx"&gt;T07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.000&lt;/span&gt;&lt;span class="nx"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, &lt;a href="https://day.js.org/docs/en/parse/string"&gt;their docs page&lt;/a&gt; contain this vague warning.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For consistent results parsing anything other than ISO 8601 strings, you should use String + Format.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This hints that, behind the scenes, Day.js is doing some extra data validation and parsing, but ultimately just using a &lt;code&gt;Date&lt;/code&gt; object for its parsing.  Since Day.js is open source we can peek behind the scenes and &lt;a href="https://github.com/iamkun/dayjs/blob/0fdac93ff2531542301b76952be9b084b2e2dfa0/src/index.js#L55"&gt;confirm this is true&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This means if you're using Day.js and want consistent parsing of non-ISO dates, you'll need to use their &lt;a href="https://day.js.org/docs/en/plugin/custom-parse-format"&gt;&lt;code&gt;CustomParseFormat&lt;/code&gt; plugin&lt;/a&gt;.  The plugin allows you to define a string format that will parse a specific date string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dayjs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dayjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customParseFormat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dayjs/plugin/customParseFormat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customParseFormat&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dayjs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;04/01/2021&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MM/DD/YYYY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;d&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="nx"&gt;T07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.000&lt;/span&gt;&lt;span class="nx"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="cm"&gt;/* ... */&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your date is of a known format and uses one of the Day.js &lt;a href="https://day.js.org/docs/en/parse/string-format#list-of-all-available-parsing-tokens"&gt;parsing tokens&lt;/a&gt; you'll be in good shape.&lt;/p&gt;

&lt;h3&gt;
  
  
  date-fns
&lt;/h3&gt;

&lt;p&gt;The last date library we'll look at is &lt;code&gt;date-fns&lt;/code&gt;, which describes itself as&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;like lodash for dates&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;date-fns&lt;/code&gt; library prides itself on its size, boasting of 200+ functions in their GitHub README.  When it comes to date parsing, &lt;code&gt;date-fns&lt;/code&gt; has a &lt;a href="https://date-fns.org/v2.21.1/docs/parseISO"&gt;&lt;code&gt;parseISO&lt;/code&gt; function&lt;/a&gt; that's explicitly for parsing full and partial ISO date strings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;datefns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date-fns&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;//...&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;datefns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parseISO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-04-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="mi"&gt;2021&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;04&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="nx"&gt;T07&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;00.000&lt;/span&gt;&lt;span class="nx"&gt;Z&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similar to the other library based solutions, this function will use the current timezone if one is not provided.&lt;/p&gt;

&lt;p&gt;If your date is &lt;em&gt;not&lt;/em&gt; an ISO like string, &lt;code&gt;datefns&lt;/code&gt; provides a a format-string based solution via &lt;a href="https://date-fns.org/v2.21.1/docs/parse"&gt;the &lt;code&gt;parse&lt;/code&gt; method&lt;/a&gt;. Similar to Day.js, the &lt;code&gt;parse&lt;/code&gt; method allows you to tell &lt;code&gt;datefns&lt;/code&gt; &lt;em&gt;how&lt;/em&gt; it should parse a date string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;gt; foo = datefns.parse('04/01/2021','MM/dd/yyyy', (new Date))
    2021-04-01T07:00:00.000Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That third required parameter is a&lt;code&gt;Date&lt;/code&gt; object -- per the docs, &lt;code&gt;parse&lt;/code&gt; will use this object to&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;define values missing from the parsed dateString&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What this means in practice we'll &lt;a href="https://github.com/date-fns/date-fns/blob/610b23d34f902bde7b67fc82154f4e68a29db104/src/parse/index.js#L362"&gt;leave as an exercise for the reader&lt;/a&gt; -- for the general case this means passing in a new &lt;code&gt;Date&lt;/code&gt; instance.&lt;/p&gt;

&lt;p&gt;Another thing to watch out for here -- those format tokens &lt;a href="https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md"&gt;aren't the same tokens&lt;/a&gt; used in other libraries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Responsibility Shifted
&lt;/h2&gt;

&lt;p&gt;As you can see, there's a variety of libraries and approaches available to a javascript developer to work around the non-ideal default behavior of javascript's &lt;code&gt;Date&lt;/code&gt; object.  However, you also may have noticed that none of their libraries attempts to solve the problem of generic date string parsing.  Instead, they offer the end-user-programmer a variety of options for dealing with date strings, but it's the client programmer's responsibility to identify which format their dates are using.&lt;/p&gt;

&lt;p&gt;Put another way, if you have a bank CSV file that includes dates in the format&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;04/01/2021
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;you'll either be writing a format string to parse this specific date format, or parsing your date string into its month/day/year parts yourself.  If you have a datasource where the date format varies, you'll be writing code to identify what format that is.&lt;/p&gt;

&lt;p&gt;This fits in with the general trend in open source code over the past 5 - 10 years.  More often than not creators and maintainers of software libraries are trying to limit the scope of what the code they put out in the world does in order to limit the scope of what they need to support in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Porting strtotime?
&lt;/h2&gt;

&lt;p&gt;After doing this all this research I had one last question -- why not just port &lt;code&gt;strtotime&lt;/code&gt; to other languages?  I went looking and found two things worth mentioning.&lt;/p&gt;

&lt;p&gt;First, the implementation of &lt;code&gt;strtotime&lt;/code&gt; is a textbook study in why other people's C code is not where you want to spend time.  You can see the guts of &lt;a href="https://github.com/php/php-src/blob/master/ext/date/lib/parse_date.re#L901"&gt;the implementation logic here&lt;/a&gt;. This isn't stock C code -- it's code &lt;a href="https://re2c.org/"&gt;for a system called re2c&lt;/a&gt;.  This system allows you to write regular expressions in a custom DSL (domain specific language), and then transform/compile those regular expressions down to C programs (also C++ and Go) that will execute those regular expressions.  Something in PHP's make file uses this &lt;code&gt;parse_date.re&lt;/code&gt; file to generate &lt;a href="https://github.com/php/php-src/blob/master/ext/date/lib/parse_date.c"&gt;&lt;code&gt;parse_date.c&lt;/code&gt;&lt;/a&gt;.  If you don't realize &lt;code&gt;parse_date.c&lt;/code&gt; is a generated file, this can be extremely rough going. If you've not familiar with &lt;code&gt;re2c&lt;/code&gt; is can be regular rough going.  We leave further exploration as an exercise for the reader -- an exercise we haven't taken ourself.&lt;/p&gt;

&lt;p&gt;So porting this function isn't a straight forward task, but there is a community driven open source package named &lt;a href="https://www.npmjs.com/package/locutus"&gt;locutus&lt;/a&gt; that's trying.  In &lt;a href="https://locutus.io/"&gt;their own words&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Locutus is a project that seeks to assimilate other languages’ standard libraries to JavaScript. Why, you ask? Well, firstly because we can of course! Apart from that, it can also serve as a nice pastime for a rainy Sunday afternoon. Not only can porting a function be quite rewarding, but it also deepens your understanding of different languages. In that sense, it is not unlike doing a crossword puzzle.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This package includes an implementation &lt;a href="https://github.com/locutusjs/locutus/blob/master/src/php/datetime/strtotime.js"&gt;of PHP's &lt;code&gt;strtotime&lt;/code&gt; function&lt;/a&gt;.  While it's &lt;a href="https://github.com/locutusjs/locutus/issues/444#issuecomment-827145252"&gt;not a direct port&lt;/a&gt; of the &lt;code&gt;re2c&lt;/code&gt; PHP regular expressions, it does seem to handle the date formats we've used in this article.  A program like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;strtotime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;locutus/php/datetime/strtotime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strtotime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;April 1, 2021&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strtotime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4/1/2021&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;strtotime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2021-04-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;results in output like this&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2021-04-01T07:00:00.000Z
2021-04-01T07:00:00.000Z
2021-04-01T07:00:00.000Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Identical dates, created with a date of midnight in the local timezone, represented as a UTC date.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>dates</category>
      <category>php</category>
    </item>
  </channel>
</rss>
