1 /**
  2  * @author Maarten van Schaik
  3  * @package Banana.Util
  4  * @summary DateTimecode 
  5  */
  6 
  7 /** @namespace Banana.Util.DateTimecode */
  8 goog.provide('Banana.Util.DateTimecode');
  9 
 10 /**
 11  * Date timecode helper class. Behaves like the regular Date class with timecode support.
 12  * 
 13  * Example:
 14    var date = new Banana.Util.DateTimecode("25-04-2011 20:23:12:13");
 15    var tc = date.getTimecode();
 16    var time = date.getTime(); 
 17  *
 18  * @param {String} data
 19  * @param {boolean} local when true we are in local time
 20  * @constructor
 21  */
 22 Banana.Util.DateTimecode = function(data,local)
 23 {
 24 	var		time = new Date;
 25 	var		FPS = 25;
 26 
 27 	/**
 28 	 * @ignore
 29 	 * @param {Object} obj
 30 	 * @returns {Object}
 31 	 */
 32 	var _init = function(obj)
 33 	{
 34 		if (!data) return;
 35 		
 36 		if(!isNaN(data))
 37 		{ 
 38 			obj.setTimecode(data);
 39 		}		
 40 		
 41 		else if (local)
 42 		{
 43 			obj.setLocalTime(data);
 44 		}
 45 		else
 46 		{
 47 			obj.setTime(data);
 48 		}
 49 		
 50 		return obj;
 51 	}
 52 	
 53 	/**
 54 	 * @return {int} timecode
 55 	 */
 56 	this.getTimecode = function() 
 57 	{
 58 		return time.getTime();
 59 	}
 60 
 61 	/**
 62 	 * @param {int} timecode
 63 	 */
 64 	this.setTimecode = function(timecode) 
 65 	{
 66 		time.setTime(timecode);
 67 		return this;
 68 	}
 69 
 70 	/**
 71 	 * Ensures pair integer
 72 	 * @ignore
 73 	 */
 74 	var dd = function(value) {
 75 		return (value<10 ? '0' : '') + value;
 76 	}
 77 	
 78 	/**
 79 	 * gets local date time by given format.
 80 	 * By default '%d-%m-%Y %H:%M:%S:%F'
 81 	 * @param {String}  format
 82 	 * @return {String}
 83 	 */
 84 	this.getLocalDateTime = function(format)
 85 	{
 86 		format = format || '%d-%m-%Y %H:%M:%S:%F';
 87 
 88 		var items = {
 89 			'H' : dd(time.getHours()),
 90 			'M' : dd(time.getMinutes()),
 91 			'S' : dd(time.getSeconds()),
 92 			'F' : dd(Math.round(time.getMilliseconds()/1000*FPS)),
 93 			'd' : dd(time.getDate()),
 94 			'm' : dd(time.getMonth()+1),
 95 			'Y' : time.getFullYear(),
 96 			'w' : time.getWeek()
 97 		};
 98 
 99 		var item;
100 		for (item in items) {
101 			format = format.replace( '%'+item, items[item] );
102 		}
103 
104 		return format;
105 	}
106 
107 	/**
108 	 * gets local time
109 	 * by default '%H:%M:%S:%F'
110 	 * @param {String} format
111 	 * @return {String}
112 	 */
113 	this.getLocalTime = function(format) {
114 		
115 		format = format || '%H:%M:%S:%F';
116 
117 		return this.getLocalDateTime(format);
118 	}
119 
120 	/**
121 	 * gets local date
122 	 * by default '%d-%m-%Y'
123 	 * @param {String} format
124 	 * @return {String}
125 	 */
126 	this.getLocalDate = function(format) {
127 		
128 		format = format || '%d-%m-%Y';
129 		return this.getLocalDateTime(format);
130 	}
131 
132 	/**
133 	 * gets date time by given format.
134 	 * By default '%d-%m-%Y %H:%M:%S:%F'
135 	 * @param {String}  format
136 	 * @return {String}
137 	 */
138 	this.getDateTime = function(format)
139 	{
140 		format = format || '%d-%m-%Y %H:%M:%S:%F';
141 
142 		var items = {
143 			'H' : dd(time.getUTCHours()),
144 			'M' : dd(time.getUTCMinutes()),
145 			'S' : dd(time.getUTCSeconds()),
146 			'F' : dd(Math.round(time.getUTCMilliseconds()/1000*FPS)),
147 			'd' : dd(time.getUTCDate()),
148 			'm' : dd(time.getUTCMonth()+1),
149 			'Y' : time.getUTCFullYear()
150 		};
151 
152 		var item;
153 		for (item in items) {
154 			format = format.replace( '%'+item, items[item] );
155 		}
156 
157 		return format;
158 	}
159 
160 	/**
161 	 * gets time
162 	 * by default '%H:%M:%S:%F'
163 	 * @param {String} format
164 	 * @return {String}
165 	 */
166 	this.getTime = function(format) 
167 	{
168 		format = format || '%H:%M:%S:%F';
169 		return this.getDateTime(format);
170 	}
171 
172 
173 	/**
174 	 * gets date
175 	 * by default '%d-%m-%Y'
176 	 * @param {String} format
177 	 * @return {String}
178 	 */
179 	this.getDate = function(format) 
180 	{	
181 		format = format || '%d-%m-%Y';
182 		return this.getDateTime(format);
183 	}
184 
185 	/**
186 	 * @ignore
187 	 * @param {String} string
188 	 * @returns {Array}
189 	 */
190 	var stringToParts = function(string)
191 	{
192 		var e = string.split(/[-: ]/);
193 
194 		// Check for missing time; only date was given
195 		if (e.length == 3)
196 		{
197 			e.push('0');
198 			e.push('0');
199 			e.push('0');
200 			e.push('0');
201 		}
202 
203 		// Check for missing date; only time was given
204 		if (e.length == 4)
205 		{
206 			e.unshift('1970');
207 			e.unshift('1');
208 			e.unshift('1');
209 		}
210 
211 		return e;
212 	}
213 
214 	/**
215 	 * sets year
216 	 * @param {int} y
217 	 * @return {this}
218 	 */
219 	this.setYear = function(y)
220 	{
221 		time.setFullYear(y);
222 		return this;
223 	}
224 	
225 	/**
226 	 * sets utc year 
227 	 * @param {int} y
228 	 * @return {this}
229 	 */
230 	this.setUTCYear = function(y)
231 	{
232 		time.setUTCFullYear(y);
233 		return this;
234 	}
235 
236 	/**
237 	 * get year 
238 	 * @return {int}
239 	 */
240 	this.getYear = function()
241 	{
242 		return time.getFullYear();
243 	}
244 
245 	/**
246 	 * get utc year 
247 	 * @return {int}
248 	 */	
249 	this.getUTCYear = function()
250 	{
251 		return time.getUTCFullYear();
252 	}
253 
254 	/**
255 	 * sets time
256 	 * @param {String} string
257 	 * @return {this}
258 	 */
259 	this.setTime = function(string)
260 	{
261 		var e = stringToParts(string);
262 
263 		time.setUTCDate( 1 ); // we need this to prevent invalidation of date object when day is changed on 31st		
264 		time.setUTCFullYear( e[2] );
265 		time.setUTCMonth( e[1]-1 );
266 		time.setUTCDate( e[0] );
267 		time.setUTCHours( e[3] );
268 		time.setUTCMinutes( e[4] );
269 		time.setUTCSeconds( e[5] );
270 		time.setUTCMilliseconds( e[6]/FPS*1000 );
271 
272 		return this;
273 	}
274 	
275 	/**
276 	 * sets local time
277 	 * @param {String} string
278 	 * @return {this}
279 	 */
280 	this.setLocalTime = function(string)
281 	{
282 		var e = stringToParts(string);
283 		
284 		time.setDate( 1 ); // we need this to prevent invalidation of date object when day is changed on 31st
285 		time.setFullYear( e[2] );
286 		time.setMonth( e[1]-1 );
287 		time.setDate( e[0] );
288 		time.setHours( e[3] );
289 		time.setMinutes( e[4] );
290 		time.setSeconds( e[5] );
291 		time.setMilliseconds( e[6]/FPS*1000 );
292 
293 		return this;
294 	}
295 
296 	/**
297 	 * @function
298 	 * Sets local date time
299 	 * @param {String} string
300 	 * @return {this}
301 	 */
302 	this.setLocalDateTime = this.setLocalTime;
303 
304 	/**
305 	 * @function
306 	 * Sets local date
307 	 * @param {String} string
308 	 * @return {this}
309 	 */
310 	this.setLocalDate = this.setLocalTime;
311 
312 	/**
313 	 * Adds date time
314 	 * @param {Banana.Util.DateTimecode} other
315 	 * @return {this}
316 	 */
317 	this.add = function(other) {
318 		this.setTimecode( this.getTimecode() + other.getTimecode() );
319 		return this;
320 	}
321 
322 	/**
323 	 * Subtracts date time
324 	 * @param {Banana.Util.DateTimecode} other
325 	 * @return {this}
326 	 */
327 	this.sub = function(other) {
328 		this.setTimecode( this.getTimecode() - other.getTimecode() );
329 		return this;
330 	}
331 
332 	/**
333 	 * Compares date time. 
334 	 * @param {Banana.Util.DateTimecode} other
335 	 * @return {int} diff between given datetime and this datetime
336 	 */
337 	this.compareTo = function(other) 
338 	{
339 		return this.getTimecode() - other.getTimecode();
340 	}
341 
342 	/**
343 	 * gets week number
344 	 * @return {int}
345 	 */
346 	this.getWeek = function()
347 	{
348 		return time.getWeek();
349 	}
350 
351 	/**
352 	 * gets day number
353 	 * @return {int}
354 	 */
355 	this.getDay = function()
356 	{
357 		return time.getDay();
358 	}
359 	
360 	/**
361 	 * gets month number
362 	 * @return {int}
363 	 */
364 	this.getMonth = function()
365 	{
366 		return time.getUTCMonth()+1;
367 	}
368 	
369 	/**
370 	 * gets local month number
371 	 * @return {int}
372 	 */
373 	this.getLocalMonth = function()
374 	{
375 		return time.getMonth()+1;
376 	}
377 	
378 	/**
379 	 * gets local month number
380 	 * @return {int}
381 	 */
382 	this.getMonthDay = function()
383 	{
384 		return time.getUTCDate();
385 	}
386 	
387 	/**
388 	 * gets local month day number
389 	 * @return {int}
390 	 */
391 	this.getLocalMonthDay = function()
392 	{
393 		return time.getDate();
394 	}
395 		
396 	/**
397 	 * @return Banana.Util.DateTimecode
398 	 * 
399 	 * @param {int} local
400 	 * @param {int} monthDay of the month. When given this day is forced
401 	 */
402 	this.addMonth = function(local,monthDay)
403 	{
404 		var month = this.getMonth()+1;
405 		var year = this.getYear();
406 		
407 		if (!monthDay)
408 		{
409 			if (local)
410 			{
411 				monthDay = this.getLocalMonthDay();
412 			}
413 			else
414 			{
415 				monthDay = this.getMonthDay();
416 			}
417 		}
418 		
419 		if (month == 13)
420 		{
421 			month = 1;
422 			year++
423 		}
424 	
425 		if (local)
426 		{
427 			this.setLocalTime(monthDay+'-'+month+'-'+year+' '+this.getLocalTime());
428 		}
429 		else
430 		{
431 			this.setTime(monthDay+'-'+month+'-'+year+' '+this.getTime());
432 		}
433 	}
434 	
435 	_init(this);
436 }
437 
438 /**
439 * Returns the week number for this date. dowOffset is the day of week the week
440 * "starts" on for your locale - it can be from 0 to 6. If dowOffset is 1 (Monday),
441 * the week returned is the ISO 8601 week number.
442 * @ignore
443 * @param int dowOffset
444 * @return int
445 */
446 Date.prototype.getWeek = function (dowOffset) {
447 /*getWeek() was developed by Nick Baicoianu at MeanFreePath: http://www.meanfreepath.com */
448 
449 dowOffset = typeof(dowOffset) == 'int' ? dowOffset : 0; //default dowOffset to zero
450 var newYear = new Date(this.getFullYear(),0,1);
451 var day = newYear.getDay() - dowOffset; //the day of week the year begins on
452 day = (day >= 0 ? day : day + 7);
453 var daynum = Math.floor((this.getTime() - newYear.getTime() -
454 (this.getTimezoneOffset()-newYear.getTimezoneOffset())*60000)/86400000) + 1;
455 var weeknum;
456 //if the year starts before the middle of a week
457 if(day < 4) {
458 weeknum = Math.floor((daynum+day-1)/7) + 1;
459 if(weeknum > 52) {
460 nYear = new Date(this.getFullYear() + 1,0,1);
461 nday = nYear.getDay() - dowOffset;
462 nday = nday >= 0 ? nday : nday + 7;
463 /*if the next year starts before the middle of
464 the week, it is week #1 of that year*/
465 weeknum = nday < 4 ? 1 : 53;
466 }
467 }
468 else {
469 weeknum = Math.floor((daynum+day-1)/7);
470 }
471 return weeknum;
472 };
473