Files
smart-date-js/src-es6/SmartDateFormat.js

248 lines
6.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class SmartDateFormat
{
constructor(format)
{
this._day = null;
this._month = null;
this._year = null;
this.loadFormat(format);
this._parseState = new SmartDateParseState();
}
loadFormat(format)
{
let index = 0;
let lowFormat = format.toLowerCase();
this._format = format;
this._parts = [];
while (index < format.length) {
index = this._scanPart(index, format, lowFormat);
}
}
_scanPart(index, format, lowFormat)
{
switch (lowFormat[index]) {
case SmartDateFormat.DAY_ANCHOR:
return this._scanDay(index, lowFormat);
case SmartDateFormat.MONTH_ANCHOR:
return this._scanMonth(index, lowFormat);
case SmartDateFormat.YEAR_ANCHOR:
return this._scanYear(index, lowFormat);
}
return this._scanStatic(index, format, lowFormat);
}
_scanDay(startIndex, lowFormat)
{
this._checkLastIsStatic();
this._day = new SmartDateDayPart();
this._parts.push(this._day);
return this._avoidAnchor(SmartDateFormat.DAY_ANCHOR, startIndex, lowFormat);
}
_scanMonth(startIndex, lowFormat)
{
this._checkLastIsStatic();
this._month = new SmartDateMonthPart();
this._parts.push(this._month);
return this._avoidAnchor(SmartDateFormat.MONTH_ANCHOR, startIndex, lowFormat);
}
_scanYear(startIndex, lowFormat)
{
this._checkLastIsStatic();
this._year = new SmartDateYearPart();
this._parts.push(this._year);
return this._avoidAnchor(SmartDateFormat.YEAR_ANCHOR, startIndex, lowFormat);
}
_avoidAnchor(anchor, startIndex, lowFormat)
{
let endingIndex = startIndex;
while (endingIndex < lowFormat.length && lowFormat[endingIndex] === anchor) {
endingIndex++;
}
return endingIndex;
}
_checkLastIsStatic()
{
if (this._parts.length === 0) {
return;
}
if (!this._parts[this._parts.length - 1].isStatic()) {
throw new Error('Dynamic date parts must be separated by static substrings');
}
}
_scanStatic(startIndex, format, lowFormat)
{
let endingIndex = startIndex;
while (endingIndex < format.length && this._isStaticAnchorSymbol(lowFormat[endingIndex])) {
endingIndex++;
}
this._parts.push(new SmartDateStaticPart(format.substring(startIndex, endingIndex)));
return endingIndex;
}
_isStaticAnchorSymbol(symbol)
{
return symbol !== SmartDateFormat.DAY_ANCHOR
&& symbol !== SmartDateFormat.MONTH_ANCHOR
&& symbol !== SmartDateFormat.YEAR_ANCHOR;
}
getPlaceHolder()
{
let placeHolder = '';
for (let i = 0; i < this._parts.length; i++) {
placeHolder += this._parts[i].placeHolder();
}
return placeHolder;
}
/**
* @param {Date} date
* @returns {String}
*/
formatDate(date)
{
var formattedDate = '';
for (let i = 0; i < this._parts.length; i++) {
if (this._parts[i].isStatic()) {
formattedDate += this._parts[i].placeHolder();
}
else {
formattedDate += this._parts[i].formatDate(date);
}
}
return formattedDate;
}
parse(value, autocomplete)
{
this._resetParseState();
this._parseState.start(value);
this._parseParts(autocomplete);
this._correctDate();
}
_resetParseState()
{
for (let i = 0; i < this._parts.length; i++) {
this._parts[i].resetState();
}
}
_parseParts(autocomplete)
{
let index = 0;
while (index < this._parts.length && (autocomplete || !this._parseState.isOver())) {
this._parts[index].parse(this._parseState);
if (!this._parts[index].isComplete()) {
return;
}
index++;
}
}
_correctDate()
{
if (!this._day.isComplete() || !this._month.isComplete()) {
return;
}
this._day.setMaximalValue(this._getMonthSize(this._month.numericValue() - 1, !this._year.isComplete() || this._isLeaPYear(this._year.numericValue())));
}
getParsedDate()
{
if (!this.isComplete()) {
return null;
}
return new Date(this._year.numericValue(), this._month.numericValue() - 1, this._day.numericValue());
}
_getMonthSize(monthIndex, isLeapYear)
{
if (monthIndex < 0 || monthIndex >= SmartDateMonthPart.MAXIMAL_VALUE) {
return SmartDateMonthPart.MAXIMAL_VALUE;
}
if (monthIndex === 1 && isLeapYear) { // February
return SmartDateFormat.BASIC_MONTH_SIZES[monthIndex] + 1;
}
return SmartDateFormat.BASIC_MONTH_SIZES[monthIndex];
}
_isLeaPYear(year)
{
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
}
getCorrectedValue()
{
let index = 0;
let value = '';
while (index < this._parts.length && !this._parts[index].isNoState()) {
value += this._parts[index].cleanedValue();
index++;
}
return value;
}
isComplete()
{
return this._parts[this._parts.length - 1].isComplete();
}
}
SmartDateFormat.DAY_ANCHOR = 'd';
SmartDateFormat.DAY_PLACEHOLDER = 'ДД';
SmartDateFormat.MONTH_ANCHOR = 'm';
SmartDateFormat.MONTH_PLACEHOLDER = 'ММ';
SmartDateFormat.YEAR_ANCHOR = 'y';
SmartDateFormat.YEAR_PLACEHOLDER = 'ГГГГ';
SmartDateFormat.BASIC_MONTH_SIZES = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];