
org.apache.myfaces.custom.calendar.resource.date.js Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
//----------------------------------------------------------------------------
// This file contains a javascript implementation of most of the
// java.text.SimpleDateFormat class, written for the purposes of implementing
// the Apache MyFaces Tomahawk calendar control.
//
// This file defines a javascript class, org_apache_myfaces_dateformat_SimpleDateFormat.
// An instance of this class can be constructed, then used to parse strings
// into dates, and format dates into strings.
//
// Note that there is one difference from SimpleDateFormat in the formatting
// string pattern; this code optionally supports ISO-8601 weeks, and the JODA
// "xxxx" pattern for weekYear.
//
// This code is a "port" of java class org.apache.myfaces.dateformat.SimpleDateFormatter
// from Apache Myfaces Tomahawk, with the minimum number of changes needed to
// make the code work in javascript. See that class for further documentation
// about the code in this file. Any "fixes" needed in the code below should
// first be implemented (and tested) in the base java version.
//
// The main differences between the java code and this javascript are that
// in java a lot of methods are declared static to ensure they do not
// accidentally change the object state. But this is very inconvenient to
// do in javascript as static function names must include the "namespace"
// prefix, eg org_apache_myfaces_dateformat_SimpleDateFormatter_foo().
// Instead, all these methods are implemented as non-static member methods.
// In addition, private methods have an underscore added to the start of
// the name. Note also that the constructor for a java.util.Date object takes
// a year relative to 1900, while javascript takes one relative to 0AD.
//----------------------------------------------------------------------------
// Constructor for DateFormatSymbols class
org_apache_myfaces_dateformat_DateFormatSymbols = function()
{
this.eras = new Array('BC', 'AD');
this.months = new Array(
'January', 'February', 'March', 'April',
'May', 'June', 'July', 'August', 'September', 'October',
'November', 'December', 'Undecimber');
this.shortMonths = new Array(
'Jan', 'Feb', 'Mar', 'Apr',
'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct',
'Nov', 'Dec', 'Und');
this.weekdays = new Array(
'Sunday', 'Monday', 'Tuesday',
'Wednesday', 'Thursday', 'Friday', 'Saturday');
this.shortWeekdays = new Array(
'Sun', 'Mon', 'Tue',
'Wed', 'Thu', 'Fri', 'Sat');
this.ampms = new Array('AM', 'PM');
this.zoneStrings = new Array(new Array(0, 'long-name', 'short-name'));
var threshold = new Date();
threshold.setYear(threshold.getYear()-80);
this.twoDigitYearStart = threshold;
}
// Constructor for ParserContext class
org_apache_myfaces_dateformat_ParserContext = function(dow)
{
this.newIndex=0;
this.invalid = false;
this.firstDayOfWeek = dow;
this.ambigousYear=false;
this.ambigousWeekYear=false;
this.year=0;
this.month=0;
this.day=1;
this.dayOfWeek=0;
this.hour=0;
this.hourAmpm;
this.min=0;
this.sec=0;
this.ampm=0;
this.weekYear=0;
this.weekOfWeekYear=0;
}
// constructor for WeekDate class
org_apache_myfaces_dateformat_WeekDate = function(year, week)
{
this.year = year;
this.week = week;
}
// constructor for StringBuffer class
org_apache_myfaces_dateformat_StringBuffer = function(s)
{
if (s == null)
this.str = "";
else
this.str = s;
var proto = org_apache_myfaces_dateformat_StringBuffer.prototype;
proto.append = function(s)
{
this.str = this.str + s;
}
proto.toString = function()
{
return this.str;
}
}
// Constructor for SimpleDateFormatter class
org_apache_myfaces_dateformat_SimpleDateFormatter = function(pattern, symbols, firstDayOfWeek)
{
this._construct(pattern, symbols, firstDayOfWeek);
}
// static initialisation block; requires constructor for SimpleDateFormatter
// to run first in order to create the prototype object that this block
// attaches methods and constants to.
{
var proto = org_apache_myfaces_dateformat_SimpleDateFormatter.prototype;
proto.MSECS_PER_SEC = 1000;
proto.MSECS_PER_MIN = 60 * proto.MSECS_PER_SEC;
proto.MSECS_PER_HOUR = 60 * proto.MSECS_PER_MIN;
proto.MSECS_PER_DAY = 24 * proto.MSECS_PER_HOUR;
proto.MSECS_PER_WEEK = 7 * proto.MSECS_PER_DAY;
proto.MONTH_LEN =
[
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
];
proto._getIsoWeekDate = function(date)
{
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
var a,b,c,d,e,f,g,s,n;
if (month <= 2)
{
a = year - 1;
b = Math.floor(a/4) - Math.floor(a/100) + Math.floor(a/400);
c = Math.floor((a-1)/4) - Math.floor((a-1)/100) + Math.floor((a-1)/400);
s = b - c;
e = 0;
f = day - 1 + 31*(month-1);
}
else
{
a = year;
b = Math.floor(a/4) - Math.floor(a/100) + Math.floor(a/400);
c = Math.floor((a-1)/4) - Math.floor((a-1)/100) + Math.floor((a-1)/400);
s = b - c;
e = s + 1;
f = day + Math.floor((153*(month-3) + 2)/5) + 58 + s;
}
g = (a + b) % 7;
d = (f + g - e) % 7;
n = f + 3 - d;
if (n<0)
{
// previous year
var resultWeek = 53 - Math.floor((g-s)/5);
return new org_apache_myfaces_dateformat_WeekDate(year-1, resultWeek);
}
else if (n > (364+s))
{
// next year
var resultWeek = 1;
return new org_apache_myfaces_dateformat_WeekDate(year+1, resultWeek);
}
else
{
// current year
var resultWeek = Math.floor(n/7) + 1;
return new org_apache_myfaces_dateformat_WeekDate(year, resultWeek);
}
}
proto._isLeapYear = function(year)
{
return ((year%4 == 0) && (year%100 != 0)) || (year%400 == 0);
}
proto._dayOfWeek = function(year, month, day)
{
month -= 2;
if (month < 1)
{
month += 12;
--year;
}
var cent = Math.floor(year / 100);
year %= 100;
var base =
Math.floor((26 * month - 2) / 10)
+ day
+ year
+ Math.floor(year/4)
+ Math.floor(cent/4)
+ (5*cent);
var dow = base % 7;
return dow;
}
proto._getWeekDate = function(date, firstDayOfWeek)
{
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
var thisIsLeapYear = this._isLeapYear(year);
var dayOfYear = day + this.MONTH_LEN[month-1];
if (thisIsLeapYear && (month>2))
{
++dayOfYear;
}
var jan1Weekday = this._dayOfWeek(year, 1, 1);
var pivotOffset = firstDayOfWeek - jan1Weekday;
if (pivotOffset > 3)
{
pivotOffset -= 7;
}
else if (pivotOffset < -3)
{
pivotOffset += 7;
}
var dayOffset = dayOfYear-1;
if (dayOffset < pivotOffset)
{
var prevIsLeapYear = this._isLeapYear(year-1);
if ((pivotOffset==3) || ((pivotOffset==2) && prevIsLeapYear))
{
return new org_apache_myfaces_dateformat_WeekDate(year-1, 53);
}
return new org_apache_myfaces_dateformat_WeekDate(year-1, 52);
}
var daysFromFirstWeekStart = (dayOfYear - 1 - pivotOffset);
var weekNumber = Math.floor(daysFromFirstWeekStart/7) + 1;
if ((weekNumber < 53)
|| (pivotOffset == -3)
|| (pivotOffset == -2 && thisIsLeapYear))
{
return new org_apache_myfaces_dateformat_WeekDate(year, weekNumber);
}
else
{
return new org_apache_myfaces_dateformat_WeekDate(year+1, 1);
}
}
proto._getStartOfWeekYear = function(year, firstDayOfWeek)
{
var d1 = new Date(year, 0, 1, 0, 0, 0);
var firstDayOfYear = d1.getDay();
var dayDiff = firstDayOfWeek - firstDayOfYear;
var dayShift;
if (dayDiff >= 4)
{
dayShift = 7 - dayShift;
}
else if (dayDiff >= 0)
{
dayShift = dayDiff;
}
else if (dayDiff >= -3)
{
dayShift = dayDiff;
}
else
{
dayShift = 7 + dayDiff;
}
var weekYearStartMsecs = d1.getTime() + (dayShift * this.MSECS_PER_DAY);
return weekYearStartMsecs;
}
proto._getDateForWeekDate = function(
year, week, day,
hour, min, sec,
firstDayOfWeek)
{
var msecsBase = this._getStartOfWeekYear(year, firstDayOfWeek);
var msecsOffset = (week-1) * this.MSECS_PER_WEEK;
msecsOffset += (day-1) * this.MSECS_PER_DAY;
msecsOffset += hour * this.MSECS_PER_HOUR;
msecsOffset += min * this.MSECS_PER_MIN;
msecsOffset += sec * this.MSECS_PER_SEC;
var finalDate = new Date();
finalDate.setTime(msecsBase + msecsOffset);
return finalDate;
}
proto._fullYearFromDate = function(year)
{
if (year < 1900)
{
return year+1900;
}
else
{
return year;
}
}
proto._createDateFromContext = function(context)
{
var date;
if (context.weekOfWeekYear != 0)
{
date = this._getDateForWeekDate(
context.weekYear, context.weekOfWeekYear, context.day,
context.hour, context.min, context.sec,
context.firstDayOfWeek);
}
else
{
date = new Date(
context.year, context.month, context.day,
context.hour, context.min, context.sec);
}
return date;
}
proto._substr = function(s, start, len)
{
var s2 = s.substring(start);
if (s2.length <= len)
return s2;
else
return s2.substring(0, len);
}
proto._parseOps = function(symbols, yearIsWeekYear, firstDayOfWeek, ops, dateStr)
{
var context = new org_apache_myfaces_dateformat_ParserContext(firstDayOfWeek);
var dateIndex = 0;
var dateStrLen = dateStr.length;
for(var i=0; (i= 4)
{
var fragment = dateStr.substring(dateIndex);
var index = this._parsePrefixOf(context, symbols.months, fragment);
if (index != -1)
{
context.month = index;
}
}
else
{
context.month = this._parseNum(context, dateStr, 2, dateIndex) - 1;
}
}
else if (c == 'd')
{
context.day = this._parseNum(context, dateStr, 2, dateIndex);
}
else if (c == 'E')
{
if (patlen <= 3)
{
var fragment = dateStr.substring(dateIndex, dateIndex+3);
var index = this._parseIndexOf(context, symbols.shortWeekdays, fragment);
if (index != -1)
{
context.dayOfWeek = index;
}
}
else
{
var fragment = dateStr.substring(dateIndex);
var index = this._parsePrefixOf(context, symbols.weekdays, fragment);
if (index != -1)
{
context.dayOfWeek = index;
}
}
}
else if (c == 'H')
{
context.hour = this._parseNum(context, dateStr, 2, dateIndex);
}
else if (c == 'h')
{
context.hourAmpm = this._parseNum(context, dateStr, 2, dateIndex);
}
else if (c == 'm')
{
context.min = this._parseNum(context, dateStr, 2, dateIndex);
}
else if (c == 's')
{
context.sec = this._parseNum(context, dateStr, 2, dateIndex);
}
else if (c == 'a')
{
context.ampm = this._parseString(context, dateStr, dateIndex, symbols.ampms);
}
else if (c == 'w')
{
context.weekOfWeekYear = this._parseNum(context, dateStr, 2, dateIndex);
}
else
{
context.invalid = true;
}
}
proto._parseInt = function(value)
{
var sum = 0;
for(var i=0;i'9')
{
return -1;
}
sum = sum*10+(c-'0');
}
return sum;
}
proto._parseNum = function(context, dateStr, nChars, dateIndex)
{
// Try to convert the most possible characters (posCount). If that fails,
// then try again without the last character. Repeat until successful
// numeric conversion occurs.
var nToParse = Math.min(nChars, dateStr.length - dateIndex);
for(var i=nToParse;i>0;i--)
{
var numStr = dateStr.substring(dateIndex,dateIndex+i);
var value = this._parseInt(numStr);
if(value == -1)
continue;
context.newIndex = dateIndex+i;
return value;
}
context.newIndex = -1;
context.invalid = true;
return -1;
}
proto._parseIndexOf = function(context, array, value)
{
for (var i = 0; i < array.length; ++i)
{
var s = array[i];
if (value == s)
{
context.newIndex += s.length;
return i;
}
}
context.invalid = true;
context.newIndex = -1;
return -1;
}
proto._parsePrefixOf = function(context, array, value)
{
for (var i=0; i 0)
{
if (context.ampm == 1)
{
context.hour = context.hourAmpm + 12;
if (context.hour == 24)
context.hour = 0;
}
else
{
context.hour = context.hourAmpm;
}
}
}
proto._formatOps = function(symbols, yearIsWeekYear, firstDayOfWeek, ops, date)
{
var context = new org_apache_myfaces_dateformat_ParserContext(firstDayOfWeek);
context.year = date.getFullYear();
context.month = date.getMonth();
context.day = date.getDate();
context.dayOfWeek = date.getDay();
context.hour = date.getHours();
context.min = date.getMinutes();
context.sec = date.getSeconds();
context.ampm = (context.hour < 12) ? 0 : 1;
var weekDate = this._getWeekDate(date, firstDayOfWeek);
context.weekYear = weekDate.year;
context.weekOfWeekYear = weekDate.week;
var str = new org_apache_myfaces_dateformat_StringBuffer();
for(var i=0; i= 4) {
out.append(symbols.months[context.month]);
}
else
{
this._formatNum(context.month+1,patlen, false, out);
}
}
else if (c=='d')
{
this._formatNum(context.day,patlen, false, out);
}
else if (c=='E')
{
if (patlen <= 3)
{
out.append(symbols.shortWeekdays[context.dayOfWeek]);
}
else
{
out.append(symbols.weekdays[context.dayOfWeek]);
}
}
else if(c=='H')
{
this._formatNum(context.hour, patlen, false, out);
}
else if (c=='h')
{
var hour = context.hour;
if (hour == 0)
{
hour = 12;
}
else if (hour > 12)
{
hour = hour - 12;
}
this._formatNum(hour, patlen, false, out);
}
else if (c=='m')
{
this._formatNum(context.min, patlen, false, out);
}
else if (c=='s')
{
this._formatNum(context.sec, patlen, false, out);
}
else if (c=='a')
{
out.append(symbols.ampms[context.ampm]);
}
else if (c=='w')
{
this._formatNum(context.weekOfWeekYear, patlen, false, out);
}
else
{
context.invalid = true;
}
}
proto._formatNum = function(num, length, ensureLength, out)
{
var str = "" + num;
while(str.length length)
{
str = str.substr(str.length - length);
}
out.append(str);
}
proto._appendToArray = function(array, obj)
{
array[array.length] = obj;
}
proto._isLetter = function(c)
{
if ((c>= 'a') && (c<='z')) return true;
if ((c>='A') && (c<='Z')) return true;
return false;
}
proto._analysePattern = function(pattern)
{
var patternIndex = 0;
var patternLen = pattern.length;
var lastChar = 0;
var patternSub = null;
var quoteMode = false;
var ops = new Array();
while (patternIndex < patternLen)
{
var currentChar = pattern.charAt(patternIndex);
var nextChar;
if (patternIndex < patternLen - 1)
{
nextChar = pattern.charAt(patternIndex + 1);
}
else
{
nextChar = 0;
}
if (currentChar == '\'' && lastChar != '\\')
{
if (patternSub != null)
{
this._appendToArray(ops, patternSub.toString());
patternSub = null;
}
quoteMode = !quoteMode;
}
else if (quoteMode)
{
if (patternSub == null)
{
patternSub = new org_apache_myfaces_dateformat_StringBuffer("q:");
}
patternSub.append(currentChar);
}
else
{
if (currentChar == '\\' && lastChar != '\\')
{
// do nothing
}
else
{
if (patternSub == null)
{
if (this._isLetter(currentChar))
{
patternSub = new org_apache_myfaces_dateformat_StringBuffer("f:");
}
else
{
patternSub = new org_apache_myfaces_dateformat_StringBuffer("l:");
}
}
patternSub.append(currentChar);
if (currentChar != nextChar)
{
this._appendToArray(ops, patternSub.toString());
patternSub = null;
}
}
}
patternIndex++;
lastChar = currentChar;
}
if (patternSub != null)
{
this._appendToArray(ops, patternSub.toString());
}
return ops;
}
proto._hasWeekPattern = function(ops)
{
var wwPresent = false;
var xxPresent = false;
for(var i=0; i
© 2015 - 2025 Weber Informatics LLC | Privacy Policy