Posts tagged with 'date'

JavaScript for C# developers: writing a library (part 2)

As I said last time, my first library object is going to be a cookie object.

Yemeni Market Datesphoto © 2007 Myscha Theriault | more info (via: Wylio)The browser API for this is remarkably simple. There’s a string property of the document object called cookie. Read from it and you get a semicolon-separated list of name=value pairs as a string. Each name is the name of a cookie and the value is its value. Write to it with a specially formatted string (again semicolon-separated) and you add or update a single cookie (you can only update a cookie one at a time). The string contains at least three parameters: a name=value pair, an expiry date for the cookie defined in UTC format, and a path from which the cookie is valid (usually everyone uses “/” for the root of the site, and this is what we’ll do). There are other parameters if you want to use them, but we’ll stick with these. Finally, to delete a cookie, you merely update it with an expiry date that’s in the past and the browser will delete it.

Things to note: the API does not give you a way to read a single cookie. You get them all and you have to parse the string looking for the one you want. You also don’t get back any ancillary information about the cookie (its expiry date, for example).

Also, it seems that we’ll need some date routines as well: we’ll need to calculate a date in the past to delete a cookie and it would be nice if we could make the expiry date optional in our API and the function calculate a date, say, a month in the future if so. Actually, for now, if you don’t mind I’ll shelve the addMonths() date function (it can be a pain to write and get right) and just have an addDays function.

Time for a jmbDate object in my library to take care of any date functions I may need. Start off with the usual base code that you’re used to by now:

(function ($) {

  var $j = $.jmbLibrary;
  var $jd = $j.date = {};

})(jQuery);

(Quickly now: an auto-execute anonymous function taking one parameter, jQuery, such that it’s known as $ inside the function. Create a new empty object called date in the jmbLibrary object and give it a cute local name. You’re getting the drift.)

First let’s write a now function to mimic .NET’s DateTime.Now property. Pretty easy:

  $jd.now = function () {
    return new Date();
  };

Now, let’s write the addDays function. We’ll make use of a couple of JavaScript’s Date functions here: first the valueOf function returns passed date as the number of milliseconds since midnight on 1st January 1970. Then we’ll use one of Date’s constructors that takes a number of milliseconds and returns a new Date object.

  var getMs = function (date) {
    return date.valueOf();
  };

  var dateFromMs = function (value) {
    return new Date(value);
  };

  $jd.addDays = function (date, days) {
    return dateFromMs(getMs(date) + days * 1000 * 60 * 60 * 24);
  };

As you can see I decided to wrap those “raw” JavaScript functions into two local functions: it makes the code perhaps a little easier to read in the addDays function and it also means I can talk about function scope again. These two new functions are local to (and visible throughout) this outer anonymous function, they will not be visible outside. The addDays function will be visible outside since I’m adding it as a function to the new jmbDate object (the two local functions are not added to this object). The closure formed by the outer function gives me the ability to have private functions just for use inside the function (and hence for use by that same jmbDate object since it can “see” them too).

Finally I decided to add an isDate function too. In the next part of this series, as I mentioned above I shall be needing to see if the expiry date has been passed in to a function or not. So, I might as well write it now.

  $jd.isDate = function (date) {
    return (!!date) && (typeof date === "object") && (date.constructor === Date);
  };

Let’s explain this code. The three parts to the boolean expression that’s returned first check that the passed in date is not undefined or null (or more rigorously is not a falsy value like 0, NaN, or the empty string, or false), that the parameter is an object, and then finally (since every object has a constructor) that it was constructed from the Date constructor.

The reason for the double negation in the first subexpression (which surely is the identity operator?) is a JavaScript quirk. It seems more obvious that I should be able to write

    return (date) && [...];

since the interpreter has to convert the date variable to a boolean in order to evaluate the expression. The quirk is that this conversion is merely temporary. With && (and || for that matter) the result of the expression may not be a boolean. In fact, if date is undefined/null, it’ll be temporarily evaluated as a boolean equal to false and the rest of the expression will be ignored. The temporary conversion is ignored and the result of the expression is date and not false, which is certainly not what we want. So I have to convert date manually to a boolean for the expression to be evaluated. One way is to split the code:

  $jd.isDate = function (date) {
    if (!date) { return false; }
    return (typeof date === "object") && (date.constructor === Date);
  };

So, if the parameter is undefined/null (or any falsy value), explicitly return false. Otherwise, the parameter has some value, and so we can do the rest of the tests on what that value might be. The method I chose is to convert the parameter to a boolean by applying the negation operator, and then apply it once again to get the sense right. A little tricky I’ll admit, but it’s very much equivalent to this kind of idiomatic code:

someText = someText || "missing";

This code says, in essence “set someText equal to itself if it’s not undefined/null, otherwise set it equal to ‘missing’”. As you can see, this code would not work at all if the temporary check for true/false were permanent.

The code that creates the jmbDate object now looks like this:

(function ($) {
  var $j = $.jmbLibrary;

  var getMs = function (date) {
    return date.valueOf();
  };

  var dateFromMs = function (value) {
    return new Date(value);
  };

  var $jd = $j.date = {};

  $jd.isDate = function (date) {
    return (!!date) && (typeof date === "object") && (date.constructor === Date);
  };

  $jd.addDays = function (date, days) {
    if (!$jd.isDate(date)) { return; }
    return dateFromMs(getMs(date) + days * 1000 * 60 * 60 * 24);
  };

  $jd.now = function () {
    return new Date();
  };

})(jQuery);

At this point, I‘ll stop until next time, when we really will start to write the cookie code.

Album cover for Friends of Mr. CairoNow playing:
Jon & Vangelis - I'll Find My Way Home
(from Friends of Mr. Cairo)


JavaScript for C# developers: date basics

A scenic diversion on the road to understanding JavaScript when you're a C# programmer.

In this episode, we'll look at dates in JavaScript.

Dates are implemented in JavaScript by the Date() constructor function, which acts like a class. You can new up a Date object in much the same way as you new up a DateTime object in C#. For instance, here's how to create a date that's equal to the date I wrote this post (Mon, Apr 27, 2009):

var today = new Date(2009, 3, 27);
console.log(today.toDateString); // outputs Mon Apr 27 2009

If you look at this code a little more carefully, you'll notice that I used 3 for the month and not 4. Yes, this is gotcha number 1: the date library in JavaScript uses zero-based month numbers. The days numbers are one-based, as you'd imagine: it's just the months that are zero-based. This is, to put it mildly, confusing.

Date objects you create are of type object. Their prototype is the Date() constructor. This prototype implements several nice methods you can use to manipulate dates, of which we've already seen one (toDateString()):

var today = new Date(2009, 3, 27);
console.log(today.getDay()); // outputs 1 (the day of the week of the date)
console.log(today.getDate()); // outputs 27 
console.log(today.getMonth()); // outputs 3
console.log(today.getYear()); // outputs 109 (the years since 1900)
console.log(today.getFullYear()); // outputs 2009
console.log(today.toDateString()); // outputs "Mon Apr 27 2009"
console.log(today.toLocaleDateString()); // outputs "Monday, April 27, 2009"
console.log(today.toUTCString()); // outputs "Mon, 27 Apr 2009 06:00:00 GMT"

There are a couple of points to note here. First, the getDay() method returns the day of the week as an integer, with Sunday as 0, Monday as 1, and so on. This can be a little confusing for C# developers, because the equivalent in .NET is the DayOfWeek property. The .NET Day property, on the other hand, is the equivalent of JavaScript's getDate() method. Note that the month is returned as a zero-based value again.

The getYear() method I include for completeness only, since different browsers implement it in different ways (despite the ECMAScript standard being very explicit about what it should do). As you can see, Firefox returns the number of years since 1900 (that's what the standard says too), however IE7 and 8 return the full year value (that is, 2009 in this example). So, I'd advise you to avoid it completely and use getFullYear() instead.

The various "toString" methods return the date in various string representations. The results are very similar between Firefox and IE here, although I'd note that toUTCString() in Firefox uses the confusing GMT suffix, whereas IE uses the more correct UTC. (There is a similar method, fully deprecated in 1999 when the ECMA standard was released, called toGMTString(). This is set equal to toUTCString(), so they do the same thing, but you might see the older version in old code.) All in all, I'd say don't depend on the output of these "toString" methods: as the standard states: "The contents of the string are implementation-dependent", but note that they would use the browser's locale (that is, the OS's locale) for the various day and month names.

As you may have guessed from the last method there, date objects also contain a time portion, that is they are DateTimes in the .NET vernacular. To create a date object with a time part you would use an overloaded constructor call:

var today = new Date(2009, 3, 27, 15, 24, 23, 300);
console.log(today.getHours()); // outputs 15
console.log(today.getMinutes()); // outputs 24
console.log(today.getSeconds()); // outputs 23
console.log(today.getMilliseconds()); // outputs 300

If you need the date/time value for right now, the equivalent of DateTime.Now, you'd use the Date constructor with no parameters:

var today = new Date();
console.log(today.toLocaleDateString()); // outputs "Monday, April 27, 2009"
console.log(today.toLocaleTimeString()); // outputs "8:14:38 PM"

There are also a set of methods that deal with setting the various parts of a date/time object: the year, the month, and so on (in essence, the same names as the getters but with "set" instead), but there are no methods that deal with date computations, such as adding a number of days to a date and so on. There is an open source library out there called Datejs which uses a "fluent" API (that is, you can write things like: Date.today().add(3).days();), but there's nothing particularly geared to C# developers used to DateTime who are coding in JavaScript. We'll take a look at that next time.

Another warning before I close this post: although Date() is a constructor function, you can actually use it as an ordinary function:

var nowAsString = Date();
console.log(nowAsString); // outputs the current date/time as a string

No matter what parameters you pass in the call, it'll ignore them and return a string representing the current date and time. Pretty useless, and it's dead confusing to boot (is it a constructor or isn't it?). My advice is don't use Date() in this way.

Album cover for Hinterland Now playing:
Aim - Fall Break
(from Hinterland)


Search

About Me

I'm Julian M Bucknall, the M because it's my middle initial and because I and the other Julian Bucknall (the movie guy) would like to differentiate ourselves.

I'm a programmer by trade, an actor by ambition, and an algorithms guy by osmosis. I write articles for PCPlus in my spare time, not that there's much of that.

Julian M Bucknall Apart from that, an ex-pat Brit, atheist, microbrew enthusiast, Pet Shop Boys fanboy, slide rule and HP calculator collector, amateur photographer, Altoids muncher.

DevExpress

I'm Chief Technology Officer at Developer Express, a software company that writes some great controls and tools for .NET and Delphi. I'm responsible for the technology oversight and vision of the company.

Validation

Validate markup as HTML5 (beta)     Validate CSS

Bottom swirl

Archives

February 2012 (3)
SMTWTFS
« Jan  
1234
567891011
12131415161718
19202122232425
26272829

Like this Archive Calendar widget? Download it here.

Social networking

Google ads

The OUT Campaign

The OUT Campaign

My Tweets

  • @TerriMorton "The Texan-ized Eiffel Tower" <shudders, whimpers in corner> /cc @rachelreese
  • One of my blog readers found this awesome picture of Roger Moore modeling a pullover in a "Father and Son" pattern http://t.co/DRs4dLSu
  • @RachelHawley First Vaseline, then a drill. It's a good job I have no imagination.
Bottom swirl