Skip to content

Instantly share code, notes, and snippets.

@jed
Forked from 140bytes/LICENSE.txt
Created June 24, 2011 10:06
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jed/1044533 to your computer and use it in GitHub Desktop.
Save jed/1044533 to your computer and use it in GitHub Desktop.
ES5-ish shim for Date.prototype.toISOString
// thanks to @fgnass and @subzey for their awesome golf skills
// annotation by @fgnass
function(a){
a=this;
return (
1e3 // Insert a leading zero as padding for months < 10
-~a.getUTCMonth() // Months start at 0, so increment it by one
*10 // Insert a trailing zero as padding for days < 10
+a.toUTCString() // Can be "1 Jan 1970 00:00:00 GMT" or "Thu, 01 Jan 1970 00:00:00 GMT"
+1e3+a/1 // Append the millis, add 1000 to handle timestamps <= 999
// The resulting String for new Date(0) will be:
// "-1010 Thu, 01 Jan 1970 00:00:00 GMT1000" or
// "-10101 Jan 1970 00:00:00 GMT1000" (IE)
).replace(
// The two digits after the leading '-1' contain the month
// The next two digits (at whatever location) contain the day
// The last three chars are the milliseconds
/1(..).*?(\d\d)\D+(\d+).(\S+).*(...)/,
'$3-$1-$2T$4.$5Z')
}
function(a){a=this;return(1e3-~a.getUTCMonth()*10+a.toUTCString()+1e3+a/1).replace(/1(..).*?(\d\d)\D+(\d+).(\S+).*(...)/,'$3-$1-$2T$4.$5Z')}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Jed Schmidt <http://jed.is>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "toISOString",
"description": "ES5-ish shim for Date.prototype.toISOString",
"contributors": ["@subzey", "@fgnass"],
"keywords": [
"ES5",
"shim",
"Date",
"toISOString"
]
}
<!DOCTYPE html>
<title>Date.prototype.toISOString</title>
<div>Expected value: <b id="expected"></b></div>
<div>Actual value: <b id="ret"></b></div>
<script>
var toISOString = function(a){a=this;return(1e3-~a.getUTCMonth()*10+a.toUTCString()+1e3+a/1).replace(/1(..).*?(\d\d)\D+(\d+).(\S+).*(...)/,'$3-$1-$2T$4.$5Z')}
, now = new Date
document.getElementById( "expected" ).innerHTML = Date.prototype.toISOString.call(now)
document.getElementById( "ret" ).innerHTML = toISOString.call(now)
</script>
@fgnass
Copy link

fgnass commented Jun 24, 2011

Good call! We're getting closer, only 2 bytes left:
function(a){a=this;return(1e3-~a.getUTCMonth()*10+a.toUTCString()+1e3+a/1e3).replace(/.(..).*?(\d\d)\D+(\d+).(\S+).*(...)/,'$3-$1-$2T$4.$5Z')}

@fgnass
Copy link

fgnass commented Jun 24, 2011

I think I've got it. 140 bytes:
function(a){a=this;return(1e3-~a.getUTCMonth()*10+a.toUTCString()+1e3+a/1).replace(/1(..).*?(\d\d)\D+(\d+).(\S+).*(...)/,'$3-$1-$2T$4.$5Z')}

@fgnass
Copy link

fgnass commented Jun 24, 2011

Here is the annotated version:

function(a){
  a=this;
  return (
     ~a.getUTCMonth() // Months start at 0, so increment it by one
     *10 // Insert a trailing zero as padding for days < 10
     -1e3 // Insert a leading zero as padding for months < 10
     +a.toUTCString() // Can be "1 Jan 1970 00:00:00 GMT" or "Thu, 01 Jan 1970 00:00:00 GMT"
     +1e3+a/1 // Append the millis, add 1000 to handle timestamps <= 999
     // The resulting String for new Date(0) will be:
     // "-1010 Thu, 01 Jan 1970 00:00:00 GMT1000" or
     // "-10101 Jan 1970 00:00:00 GMT1000" (IE)
   ).replace(
      // The two digits after the leading '-1' contain the month
      // The next two digits (at whatever location) contain the day
      // The last three chars are the milliseconds
      /1(..).*?(\d\d)\D+(\d+).(\S+).*(...)/,
     '$3-$1-$2T$4.$5Z')
};

@jed
Copy link
Author

jed commented Jun 25, 2011

there is so much genius in this, @fgnass and @subzey. awesome work.

@subzey
Copy link

subzey commented Jun 25, 2011

@fgnass, that's amazing! Great job!

@jed
Copy link
Author

jed commented Jul 11, 2011

hey @fgnass, would you mind fixing your package.json?

@fgnass
Copy link

fgnass commented Jul 11, 2011

I'm confused, isn't this your gist @jed?

@jed
Copy link
Author

jed commented Jul 11, 2011

ha ha, so it is. i mistook the most helpful person here for the author...

@jdalton
Copy link

jdalton commented Aug 22, 2011

This ES5 shim result is inconsistent with that specified in ES5.
Here is a simple test to demonstrate the problem.

Native:     2011-08-22T16:33:02.467Z;
140byt.es: -2011-08-22T16:33:02.467Z; // notice the leading `-`
es5-shim:   2011-08-22T16:33:02.467Z;

Note: If you run the test file in Opera you may see that the milliseconds are not displayed. This is because in ES 5 they were optional, but in the current standard, ES 5.1, they are required.

@fgnass
Copy link

fgnass commented Aug 22, 2011

Some lines are swapped in the annotated version. If you use the raw one it works as expected. Here's a quick-fix:

function(a){
  a=this;
  return (
     1e3 // Insert a leading zero as padding for months < 10
     -~a.getUTCMonth() // Months start at 0, so increment it by one
     *10 // Insert a trailing zero as padding for days < 10
     +a.toUTCString() // Can be "1 Jan 1970 00:00:00 GMT" or "Thu, 01 Jan 1970 00:00:00 GMT"
     +1e3+a/1 // Append the millis, add 1000 to handle timestamps <= 999
     // The resulting String for new Date(0) will be:
     // "-1010 Thu, 01 Jan 1970 00:00:00 GMT1000" or
     // "-10101 Jan 1970 00:00:00 GMT1000" (IE)
   ).replace(
      // The two digits after the leading '-1' contain the month
      // The next two digits (at whatever location) contain the day
      // The last three chars are the milliseconds
      /1(..).*?(\d\d)\D+(\d+).(\S+).*(...)/,
     '$3-$1-$2T$4.$5Z')
}

@jed Just noticed that test.html still uses the an old version ...

@jdalton
Copy link

jdalton commented Aug 22, 2011

Also by spec Date.prototype.toUTCString is implementation-dependent.
This means shims using this take a chance because the value may not always be predictable and could cause an incorrect result (the current gist handles output variations of IE vs most other browsers).

@atk
Copy link

atk commented Aug 23, 2011

@jdalton: The result of an implementation-dependent native function may be unpredictable anyway. You seem to forget the second part to the following rule: "1. Don't use shims, 2. unless you know what you're doing".

@jed
Copy link
Author

jed commented Aug 23, 2011

@fgnass, thanks for the tip. fixed.

@jdalton
Copy link

jdalton commented Aug 23, 2011

@atk

The result of an implementation-dependent native function may be unpredictable anyway.

That's true, but Date#toISOString is not implementation-dependant so making a shim using another method that is can create inconsistencies.

You seem to forget the second part to the following rule: "1. Don't use shims, 2. unless you know what you're doing".

I'm sure Prototype/MooTools thought they knew what they were doing when they added toJSON to Array.prototype, but what they didn't anticipate was it later breaking native JSON support. Defensive programming can't hurt and neither can giving devs a heads up on potential problems.

@atk
Copy link

atk commented Aug 23, 2011

@jdalton: let's have a look at this problem in potentia you are talking about. Either, a current browser vendor changes his implementation (which is altogether unlikely) or a new browser vendor comes forth with a new implementation that is not compatible to all existing implementations (which is still most unlikely, because a new browser will have to be as conforming to existing defaults as possible to be able to compete in this market). In this case, the potential problem is as clear as it is unlikely to ever become a real issue. On the other hand, the Prototype/MooTools were not able to anticipate the native support when they implemented .toJSON, so your analogy is invalid.

@jdalton
Copy link

jdalton commented Aug 23, 2011

@atk

or a new browser vendor comes forth with a new implementation that is not compatible to all existing implementations (which is still most unlikely, because a new browser will have to be as conforming to existing defaults as possible to be able to compete in this market).

I wish it was as simple as "most unlikely". Unfortunately mobile/portable browsers have taught me to expect the unexpected.

On the other hand, the Prototype/MooTools were not able to anticipate the native support when they implemented .toJSON, so your analogy is invalid.

Actually, if they did some research at the time, they could have avoided the issue because draft spec existed and was not compatible with each lib's implementation.

The point is not to rely on observed non-spec'ed/implementation-dependant behavior because something will usually come back to bite you later.
If you avoid unnecessary risks, in this case relying on a method that's implementation-dependant, it will help produce a more stable result which is something I think we all can agree is a good thing.

@atk
Copy link

atk commented Aug 23, 2011

I haven't yet heard of a whole new browser in the mobile market since Nokia started the new Ovi Browser last year (which is derived from the Novarra browser and does not support .prototype anyway). Most other new versions are just using Webkit with either the original js engine or Google's V8. It's more the older browsers lacking in conforming support than the newer ones.

A draft spec is not already a standard and may be changed or even disbanded. It is very easy for you to claim they could have foreseen that afterwards. And while I'm at it: if we were in here to avoid unnecessary risks, we wouldn't do code golfing for a sport and develop in Java instead of JavaScript. You are barking up the wrong tree here, @jdalton

@jdalton
Copy link

jdalton commented Aug 23, 2011

@atk

Most other new versions are just using Webkit with either the original js engine or Google's V8. It's more the older browsers lacking in conforming support than the newer ones.

Not all versions and builds of WebKit, Opera, even NetFront are equal. There are bugs between versions, device firmwares, and components.

A draft spec is not already a standard and may be changed

Some minor parts may change but it could have given them a heads up to the general direction the spec was going and what to avoid.

And while I'm at it: if we were in here to avoid unnecessary risks, we wouldn't do code golfing

I've written several times that code golf is probably not appropriate for ES5 compatibility fallbacks.
You are totally free to write code however you want, just try not to get offended when I, or others, take the time to constructively critique it ;D
I think any further discussion should go off-gist you can message me directly through GitHub (and from there IMs if you want).

@atk
Copy link

atk commented Aug 24, 2011

@jdalton: If your critique would have been constructive (i.e. helping us achieving our goal better), it would have been welcome. I already told you that we are not here to deliver code that should be used in the wild. You have seen (and probably read) our homepage, so you should know we are here to explore the darker parts of the language. Whatever goals we set ourselves, is ours to choose, not yours. Therefore, your critique is not only unjustified, but a nuisance.

@jdalton
Copy link

jdalton commented Aug 24, 2011

@atk

If your critique would have been constructive (i.e. helping us achieving our goal better), it would have been welcome.

It was constructive because I took the time to point to spec sections, explain potential problems (and provide additional explanation/clarification when asked), create tests and alert gist owners/viewers of incorrect or buggy results all in a non-mean or hateful manner.

Therefore, your critique is not only unjustified, but a nuisance.

I originally visited 140byt.es and saw keywords selections for "es5", "ecmascript5", "pollyfills" that referenced gists with misleading titles suggesting support and compliance that the snippets couldn't back up. I commented on each gist, and as mentioned above, pointed to spec, gave examples of errors, and provided tests when needed. I'm not sure how that could have possibly struck a nerve with you but I'm sorry if I hurt your feelings. On the bright side you have been the only person to respond in an aggressively negative manner to my 140byt.es gist comments.
I hope others will at least learn a thing or two about spec, quirks and stability as it is my goal to inform/educate.

@atk
Copy link

atk commented Aug 24, 2011

@jdalton: I am not at all aggressive. I have not used any but polite language nor have I tried to threaten, hurt or intimidate you in any way - and what you feel to be negative is my currently futile attempt to help you recognizing you are still missing the point: The people here are already informed about the specs. They know the quirks of the language (otherwise they would not be as proficient golfing down the codes to the limit).

They still want to try creating working shims and other stuff within a 140bytes restriction - knowing that they might fail, knowing that they may not achieve full standard/spec compatibility within that constraints or that the result may not be usable in a real-life application.

Your wish to inform about standards and their value deserves respect, though you might want to try to promote it in a less self-righteous manner, lest the people you try to convince are not discouraged by it.

@jdalton
Copy link

jdalton commented Aug 24, 2011

I am not at all aggressive. I have not used any but polite language

Not sure how else to read these...



... maybe something is lost in the translation.

The people here are already informed about the specs. They know the quirks of the language (otherwise they would not be as proficient golfing down the codes to the limit)

I don't believe this is universally the case as I have helped explain spec'ed methods to more than a couple devs who participate in code golf.
In fact some of the quirks, I recently commented on, the browser vendors themselves were not aware of until last week when I reported the issues.

though you might want to try to promote it in a less self-righteous manner,

Thanks for another not-so-subtle ad hominem attack.

@atk
Copy link

atk commented Aug 24, 2011

If you cite someone, be sure, to include the (context)[https://gist.github.com/1039813]. While my comments may in some cases be less than couteous, they certainly are not threatening, hurtful or intimidating. For example: "barking up the wrong tree" is just an english idiom for "missing the point" and not literally meant to degrade you to a canine being. And you are welcome about the hint about the way you appear to be promoting your concern: nobody likes a "I'm holier-than-you"-lecture - especially if they intend to sin anyway. Please keep this in mind when you try to teach others about standards.

@jdalton
Copy link

jdalton commented Aug 24, 2011

If you cite someone, be sure, to include the (context).

I actually did in the comment before last (the "aggressively negative manner" link).

While my comments may in some cases be less than couteous, they certainly are not threatening, hurtful or intimidating

That's great because I didn't describe them as "threatening, hurtful or intimidating", but as "an aggressively negative manner" which your comments were/are.

And you are welcome about the hint about the way you appear to be promoting your concern: nobody likes a "I'm holier-than-you"-lecture - especially if they intend to sin anyway. Please keep this in mind

I don't think reporting potential problems and bugs or defending my motives/feedback (in response to you labeling it as an unjustified nuisance) makes me "holier-than-you" ;)

@mathiasbynens
Copy link

NO.

@jed
Copy link
Author

jed commented Aug 24, 2011

@jdalton, given the reception you're getting here, i get the sense you may be best off taking your ES5 abstinence agenda elsewhere.

Copy link

ghost commented Aug 24, 2011

@jed First, I believe that @jdalton has raised a perfectly valid point: shims that claim to be ECMAScript 5 compliant should be ECMAScript 5 compliant, without deviating from the specification...otherwise, they cannot legitimately be considered ES 5 shims (unless, of course, it is impossible to implement the functionality in ES 3, which is not the case here). Secondly, I humbly request that you refrain from egregiously assuming others' intentions in the future. John-David was merely attempting to provide a constructive critique to assist the community; if you cannot tolerate that, you shouldn't be on GitHub.

@jed
Copy link
Author

jed commented Aug 24, 2011

given that

  1. this shim makes no "claim to be ECMAScript 5 compliant",
  2. ES5 conformance is less important than byte count for this project,
  3. 140bytes gist comments are for golfing, not hand-wringing, and
  4. this has been explained repeatedly without success,

i'm going to start moderating comments accordingly. please stay on topic.

Copy link

ghost commented Aug 24, 2011

@jed Thank you for clarifying your position. All your points are valid, with the exception of the first: the description of this Gist reads, "ES5 shim for Date.prototype.toISOString." This snippet does not aspire to be an ES 5 shim, as you have made clear; thus, I respectfully suggest updating the title accordingly.

Edit: Thank you for updating the title.

@fgnass
Copy link

fgnass commented Aug 25, 2011

I wouldn't mind calling this function "ES5 compliant" as the function itself behaves as expected in all tested browsers.

We should add a big warning though, that explains that there are better (read more future-proof) ways to implement this, but which unfortunately don't fit into 140 bytes.

Perhaps @jed could create another Gist with his original implementation and link to it, so that others can try to golf enough bytes out of it. Even if that might be impossible, it would still be a good documentation resource.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment