Not just for print publications
This very generic function was designed to determine the publication volume and issue numbers for newspapers publishing 7 days a week. It can be used, however to compare any two dates. Just let volume represent years and issue represent days.
Of interest in this function is the methods of validating the arguments. ECMA script, JavaScript, and ExtendScript don't do nice jobs of validating object types. Looking at a constructor is as about as good as you can get, and even that isn't totally foolproof -- though it would take more than a fool to break it.
Also in this function is one of several ways to create a duplicate date object. In this case creating a new date by parsing the original date. Setting one date to another date with just an = will cause both variables to respond to a method applied to either one.
//
function determineVolumeAndIssue (pubDate, refDate, refVolume) {
//-------------------------------------------------------------------------
//-- D E T E R M I N E V O L U M E A N D I S S U E
//-------------------------------------------------------------------------
//-- Generic: Yes. Should work with any ECMA based scripting language
//-- including ExtendScript and JavaScript.
//-------------------------------------------------------------------------
//-- Purpose: To return an object with the publication volume and
//-- publication issue for a passed publication date given a reference
//-- date and the volume number on that reference date. This function
//-- can also be used to count forwards or backwards in years and days
//-- between
//-------------------------------------------------------------------------
//-- Arguments:
//-- pubDate: a Date object for the publication date. Or, if you are
//-- comparing dates, this is the date you want to investigate.
//-- refDate: a Date object. This date is the date that Issue 1 for the
//-- passed volume number was published (will be published).
//-------------------------------------------------------------------------
//-- Calls: Nothing.
//-------------------------------------------------------------------------
//-- Returns: a custom object with two properties:
//-- .volume: a Number for the volume number
//-- .issue: a Number for the issue number
//-- NOTE: both values are set to -1 if any of the arguments are
//-- incorrect.
//-------------------------------------------------------------------------
//-- Sample Use:
//~ var pubDate = new Date (Date.parse('April 21, 2010')) ;
//~ var refDate = new Date (Date.parse('August 4, 2009')) ;
//~ var refVolume = 101 ;
//~ var vi = determineVolumeAndIssue (pubDate, refDate, refVolume) ;
//~ var volume = vi.volume ;
//~ var issue = vi.issue ;
//-------------------------------------------------------------------------
//-- Notes:
//-- The refDate is the date of Issue 1 for the refVolume. The
//-- function assumes a daily publication schedule.
//-- This version does not work for 1-6 days per week. That code is more
//-- complex and not posted with this version.
//-- Issues are always positive numbers. If the refDate is after the
//-- pubDate, the Volume number will be decremented, but the Issue
//-- number will still be a postive.
//-- See the note about return values
//-------------------------------------------------------------------------
//-- Written: 2010.04.21 by Jon S. Winters of electronic publishing support
//-- eps@electronicpublishingsupport.com
//-------------------------------------------------------------------------
//-- create the return object with the default error values
var ro = {volume:-1, issue:-1} ;
//-- Verify that the arguments are valid, leaving them as separate if
//-- statuements to make it easier to debug.
if ((typeof pubDate != 'object') || (pubDate.constructor.name != 'Date')) {
return ro ;
}
else if ((typeof refDate != 'object') || (refDate.constructor.name != 'Date')) {
return ro ;
}
else if (isNaN (refVolume = parseInt (refVolume))) {
return ro ;
}
//-- Get a two key comparisons
var y0 = refDate.getYear () ;
var y1 = pubDate.getYear () ;
//-- Create a comparison date to determine if the current date
//-- is before or after the volume referece date.
//-- Using the Date.parse because just setting the date creates
//-- a pointer which then destroys the volumeReferenceDate.
//-- this is slightly slower, but not a deathly slow
var comparisonDate = new Date (Date.parse (refDate)) ;
//-- Move to the same year as the passed date
comparisonDate.setYear (1900 + y1) ;
var timeDifference = comparisonDate.getTime () - pubDate.getTime () ;
//-- Using the time difference determine if we are a before or after the
//-- reference date, add {using the normal ids for Issue and Volume}
//-- calcuate the volume and issue numbers and put them back into
//-- the passed object.
if (0 >= timeDifference) {
//-- we are this number of issues past the volume referece date
ro.issue = String (1 + Math.ceil (Math.abs(timeDifference) / (1000 * 60 * 60 * 24))) ;
ro.volume = String (Math.floor (y1 - y0) + refVolume) ;
}
else {
//-- back up a year.
comparisonDate.setYear (1900 + (y1 - 1)) ;
timeDifference = comparisonDate.getTime () - pubDate.getTime () ;
ro.issue = String (1 + Math.ceil (Math.abs (timeDifference) / (1000 * 60 * 60 * 24))) ;
ro.volume = String (Math.floor ((y1 -1) - y0) + refVolume) ;
}
//-- all done
return ro ;
}
//
//