com.altova.functions.DateTimeFormatParser Maven / Gradle / Ivy
////////////////////////////////////////////////////////////////////////
//
// DateTimeFormatParser.java
//
// This file was generated by MapForce 2017sp2.
//
// YOU SHOULD NOT MODIFY THIS FILE, BECAUSE IT WILL BE
// OVERWRITTEN WHEN YOU RE-RUN CODE GENERATION.
//
// Refer to the MapForce Documentation for further details.
// http://www.altova.com/mapforce
//
////////////////////////////////////////////////////////////////////////
package com.altova.functions;
import java.util.Calendar;
import java.util.GregorianCalendar;
import com.altova.types.DateTime;
public class DateTimeFormatParser {
public DateTimeFormatParser( final String sPattern)
{
mPattern = sPattern;
mFieldOpen = '[';
mFieldClose = ']';
}
public String formatDateTime( DateTime dt )
{
String sOutput = "";
int nLength = mPattern.length();
ParseState state = ParseState.NORMAL;
ArgumentState argState = ArgumentState.COMPONENT;
FieldInfo fieldInfo = new FieldInfo();
for( int i = 0; i < nLength; ++i)
{
char cCurrent = mPattern.charAt(i);
char cNext = i + 1 < nLength ? mPattern.charAt(i + 1) : 0;
switch( state )
{
case NORMAL:
{
if( cCurrent == mFieldOpen )
{
if( cNext != mFieldOpen )
{
state = ParseState.INFIELD;
argState = ArgumentState.COMPONENT;
fieldInfo.reset();
}
else
{
sOutput += cCurrent;
i++;
}
}
else if( cCurrent == mFieldClose )
{
if( cNext != mFieldClose )
{
//error something is wrong with the pattern
throw new IllegalArgumentException( "Incorrect pattern: '" + mPattern + "'");
}
else
{
sOutput += cCurrent;
i++;
}
}
else
{
sOutput += cCurrent;
}
}
break;
case INFIELD:
{
if( cCurrent == mFieldClose )
{
if( cNext != mFieldClose )
{
state = ParseState.NORMAL;
if( fieldInfo.mComponent > 0 )
{
String sValue = getComponentValue(dt, fieldInfo.mComponent);
if ((fieldInfo.mComponent != 'z' && fieldInfo.mComponent != 'Z') || (dt.hasTimezone() != DateTime.TZ_MISSING))
sValue = processFormatModifier( dt, sValue, fieldInfo);
sValue = processWidth( sValue, fieldInfo);
sOutput += sValue;
}
}
else
{
//error ]] in field
throw new IllegalArgumentException( "Incorrect pattern: '" + mPattern + "'");
}
}
else
{
switch( argState )
{
case COMPONENT:
{
fieldInfo.mComponent = cCurrent;
argState = ArgumentState.FORMAT;
}
break;
case FORMAT:
{
if( cCurrent == ',' )
argState = ArgumentState.WIDTH;
else
fieldInfo.mModifier += cCurrent;
}
break;
case WIDTH:
{
fieldInfo.mWidth += cCurrent;
}
break;
}
}
}
break;
}
}
if( state != ParseState.NORMAL )
throw new IllegalArgumentException( "Incorrect pattern: '" + mPattern + "'");
return sOutput;
}
protected String processFormatModifier(
final DateTime dtData,
final String sValue,
FieldInfo fieldInfo)
{
if( fieldInfo.mModifier.length() == 0 )
{
// set presentation defaults
if( fieldInfo.mComponent == 'F' || fieldInfo.mComponent == 'P' )
fieldInfo.mModifier = "n";
else if( fieldInfo.mComponent == 'm' || fieldInfo.mComponent == 's' )
fieldInfo.mModifier = "01";
else
fieldInfo.mModifier = "1";
}
String sResult = sValue;
int nZeroPad = 0;
while( fieldInfo.mModifier.charAt(nZeroPad) == '0' ) nZeroPad++;
if( fieldInfo.mModifier.substring(nZeroPad).equals("1") )
{
StringBuffer sbResult = new StringBuffer(sValue);
if( fieldInfo.mComponent == 'F' )
{
sbResult = new StringBuffer();
int day = dtData.getValue().get( Calendar.DAY_OF_WEEK);
day = day == 1 ? 7 : day - 1; //strange calendar
sbResult.append( day );
fieldInfo.mComponent = 'D'; //prevent processWidth to handle the output as string
}
//add padding zeros
int nLength = sbResult.length();
if( sbResult.length() < nZeroPad + 1 )
for( int i = 0; i < nZeroPad + 1 - nLength; i++) sbResult.insert(0, '0');
sResult = sbResult.toString();
}
else if( fieldInfo.mModifier.equals("N")
|| fieldInfo.mModifier.equals("n")
|| fieldInfo.mModifier.equals("Nn") )
{
sResult = getComponentNameValue( dtData, fieldInfo);
if( fieldInfo.mModifier.equals("N") )
sResult = sResult.toUpperCase();
else if( fieldInfo.mModifier.equals("n") )
sResult = sResult.toLowerCase();
}
else
{
throw new IllegalArgumentException( "Unknown format modifier: '" + fieldInfo.mModifier + "'");
}
return sResult;
}
protected String processWidth(
final String sValue,
FieldInfo fieldInfo)
{
if( fieldInfo.mWidth.length() == 0 )
return sValue;
StringBuffer sResult = new StringBuffer(sValue);
int nLength = sResult.length();
fieldInfo.Analyze();
if( fieldInfo.mMaxWidth > 0 )
{
if( fieldInfo.mMaxWidth >= fieldInfo.mMinWidth )
{
if( nLength > fieldInfo.mMaxWidth )
{
if( fieldInfo.mComponent != 'Y' )
sResult.delete( fieldInfo.mMaxWidth, nLength );
else
sResult.delete( 0, nLength - fieldInfo.mMaxWidth );
}
}
}
if( fieldInfo.mMinWidth > nLength)
{
if( fieldInfo.mComponent != 'F' ) // F day of week, is currently the only text and should be padded with ' '
for( int i = 0; i < fieldInfo.mMinWidth - nLength; i++) sResult.insert(0, '0');
else
for( int i = 0; i < fieldInfo.mMinWidth - nLength; i++) sResult.append(' ');
}
return sResult.toString();
}
protected String getComponentNameValue(
DateTime dtData,
FieldInfo fieldInfo)
{
String sValue;
switch( fieldInfo.mComponent )
{
case 'M':
sValue = MonthNames[dtData.getMonth() - 1];
fieldInfo.mComponent = 'F'; //this allows the process width to handle the result as Text
break;
case 'D':
sValue = DayNames[ dtData.getValue().get( Calendar.DAY_OF_WEEK) ];
fieldInfo.mComponent = 'F'; //this allows the process width to handle the result as Text
break;
default:
sValue = getComponentValue(dtData, fieldInfo.mComponent);
}
return sValue;
}
protected String getComponentValue( DateTime dtData, char cComponent)
{
StringBuffer sValue = new StringBuffer();
switch( cComponent )
{
case 'd': sValue.append( dtData.getValue().get( Calendar.DAY_OF_YEAR) ); break;
case 'D': sValue.append( dtData.getDay() ); break;
case 'F': sValue.append( DayNames[ dtData.getValue().get( Calendar.DAY_OF_WEEK) ] ); break;
case 'M': sValue.append( dtData.getMonth() ); break;
case 'Y': sValue.append( dtData.getYear() ); break;
case 'W':
{
Calendar cal = dtData.getValue();
cal.setMinimalDaysInFirstWeek( 4);
cal.setFirstDayOfWeek(Calendar.MONDAY);
sValue.append(cal.get( Calendar.WEEK_OF_YEAR) );
}
break;
case 'w':
{
Calendar cal = dtData.getValue();
cal.setFirstDayOfWeek(Calendar.MONDAY);
sValue.append(cal.get( Calendar.WEEK_OF_MONTH) );
}
break;
case 'P': sValue.append( dtData.getHour() < 12 ? "A.M." : "P.M." ); break;
case 'H': sValue.append( dtData.getHour() ); break;
case 'h':
{
long h = dtData.getHour();
if (h > 12)
h -= 12;
else if (h == 0)
h = 12;
sValue.append(h);
}
break;
case 'm':
{
sValue.append( dtData.getMinute() );
if( sValue.length() < 2)
sValue.insert( 0, '0' );
}
break;
case 's':
{
sValue.append( dtData.getSecond() );
if( sValue.length() < 2)
sValue.insert( 0, '0' );
}
break;
case 'f':
{
short nSecs = (short)(dtData.getPartSecond());
double nMilSecs = dtData.getPartSecond();
nMilSecs -= nSecs;
sValue.append( String.format("%5.3f", nMilSecs).substring(2) );
}
break;
case 'z': if( dtData.hasTimezone() != DateTime.TZ_MISSING) sValue.append( "GMT" );
case 'Z':
{
if( dtData.hasTimezone() != DateTime.TZ_MISSING)
{
StringBuffer hour = new StringBuffer();
hour.append( Math.abs(dtData.getTimezoneOffset() / 60) );
StringBuffer mins = new StringBuffer();
mins.append( Math.abs(dtData.getTimezoneOffset() % 60) );
sValue.append( dtData.getTimezoneOffset() >= 0 ? '+' : '-' );
sValue.append( hour.length() < 2 ? '0' + hour.toString() : hour.toString() );
sValue.append(':');
sValue.append(mins.length() < 2 ? '0' + mins.toString() : mins.toString() );
}
}
break;
default:
throw new IllegalArgumentException( "Unknown component specifier: '" + cComponent + "'");
}
return sValue.toString();
}
public DateTime parseDateTime( String sInput)
{
String sPattern = mPattern.trim();
StringBuffer sbInput = new StringBuffer(sInput);
ParseState state = ParseState.NORMAL;
ArgumentState argState = ArgumentState.COMPONENT;
FieldInfo fieldInfo = new FieldInfo();
DateTimeData dt = new DateTimeData();
int nLength = sPattern.length();
for( int i = 0; i < nLength; ++i)
{
char cCurrent = sPattern.charAt(i);
char cNext = i + 1 < nLength ? sPattern.charAt(i + 1) : 0;
switch( state )
{
case NORMAL:
{
if( cCurrent == mFieldOpen )
{
if( cNext != mFieldOpen )
{
state = ParseState.INFIELD;
argState = ArgumentState.COMPONENT;
fieldInfo.reset();
}
else
{
i++;
if( cCurrent == sbInput.charAt(0) )
{
sbInput.deleteCharAt(0);
}
else
{
throw new IllegalArgumentException( "Pattern not matching field opening '" + mFieldOpen + "'. Unable to read: '" + sbInput.toString() + "'");
}
}
}
else
{
if( cCurrent == sbInput.charAt(0) )
{
sbInput.deleteCharAt(0);
}
else
{
throw new IllegalArgumentException( "Pattern doesn't match! Unable to read: '" + sbInput.toString() + "'");
}
}
}
break;
case INFIELD:
{
if( cCurrent == mFieldClose )
{
if( cNext != mFieldClose )
{
state = ParseState.NORMAL;
if( fieldInfo.mComponent > 0 )
{
//Analyze field read min and max width
fieldInfo.Analyze();
//Read the field from input and apply correct value
ReadField( dt, fieldInfo, sbInput, cNext);
}
}
else
{
i++;
}
}
else
{
switch( argState )
{
case COMPONENT:
{
fieldInfo.mComponent = cCurrent;
argState = ArgumentState.FORMAT;
}
break;
case FORMAT:
{
if( cCurrent == ',' )
argState = ArgumentState.WIDTH;
else
fieldInfo.mModifier += cCurrent;
}
break;
case WIDTH:
{
fieldInfo.mWidth += cCurrent;
}
break;
}
}
}
break;
}
}
int[] monthTable = new GregorianCalendar().isLeapYear( dt.Year ) ? monthStartLeap : monthStart;
if( dt.DayOfYear > 0 && dt.DayOfYear <= monthTable[12] )
{
int i = 12;
while( monthTable[i] >= dt.DayOfYear ) i--;
dt.Day = dt.DayOfYear - monthTable[i];
dt.Month = i + 1;
}
boolean b2400 = dt.Hour == 24 && dt.Minute == 0 && dt.Second == 0;
if (b2400)
{
dt.Hour = 0;
if (dt.Year == 0)
dt.Year = 1;
}
DateTime result = new DateTime();
result.setMonth(dt.Month);
result.setYear(dt.Year);
result.setDay(dt.Day);
result.setHour(dt.Hour);
result.setMinute(dt.Minute);
result.setSecond(dt.Second);
result.setPartSecond(dt.MilliSecond);
if( dt.TimeZone != 0)
result.setHasTimezone(DateTime.TZ_OFFSET);
result.setTimezoneOffset(dt.TimeZone);
if (b2400)
{
long v = result.getTimeValue();
v += (86400 * 1000);
result.setDateFromTimeValue(v);
}
return result;
}
boolean StringToRead( String sModifier)
{
if( sModifier.equals("N") || sModifier.equals("n") || sModifier.equals("Nn") )
return true;
else
return false;
}
int ReadNumber( StringBuffer sbInput, int nMax )
{
return ReadNumberWithSize( sbInput, nMax).number;
}
int ReadFieldNumber( StringBuffer sbInput, FieldInfo fieldinfo )
{
int number;
int nMax = fieldinfo.mMaxWidth;
StringBuffer sbNumber = new StringBuffer("");
sbInput = Lang.trimLeft(sbInput, " t"); //trim beginning spaces
int i = 0;
nMax = nMax == 0 ? sbInput.length() : nMax > sbInput.length() ? sbInput.length() : nMax;
for (;i < nMax && Character.isDigit( sbInput.charAt(i) ); ++i)
{
sbNumber.append(sbInput.charAt(i));
}
if ( fieldinfo.mMinWidth > 0 && i < fieldinfo.mMinWidth )
{
throw new IllegalArgumentException( "Pattern component '" + fieldinfo.mComponent + "' has minimum length of " + fieldinfo.mMinWidth + "! Unable to read: '" + sbInput + "'" );
}
sbInput.delete(0, i);
try {
number = Integer.parseInt( sbNumber.toString());
}
catch (NumberFormatException e) {
number = 0;
}
return number;
}
private class SizeNumber {
int size;
int number;
}
SizeNumber ReadNumberWithSize( StringBuffer sbInput, int nMax )
{
StringBuffer sbNumber = new StringBuffer("");
sbInput = Lang.trimLeft(sbInput, " t"); //trim beginning spaces
int i = 0;
nMax = nMax == 0 ? sbInput.length() : nMax > sbInput.length() ? sbInput.length() : nMax;
for (;i < nMax && Character.isDigit( sbInput.charAt(i) ); ++i)
{
sbNumber.append(sbInput.charAt(i));
}
sbInput.delete(0, i);
SizeNumber sn = new SizeNumber();
sn.size = i;
try {
sn.number = Integer.parseInt( sbNumber.toString());
}
catch (NumberFormatException e) {
sn.number = 0;
}
return sn;
}
private String ReadStringUntil( StringBuffer sbInput, int nMax, char cUntil )
{
StringBuffer sbRead = new StringBuffer("");
int i = 0;
nMax = nMax == 0 ? sbInput.length() : nMax > sbInput.length() ? sbInput.length() : nMax;
for (;i < nMax && sbInput.charAt(i) != cUntil; ++i)
{
sbRead.append( sbInput.charAt(i) );
}
sbInput.delete(0, i);
return sbRead.toString();
}
private void ReadField(
DateTimeData dtData,
FieldInfo fieldinfo,
StringBuffer sbInput,
char cNext)
{
String sInputBackup = sbInput.toString();
switch( fieldinfo.mComponent )
{
case 'd': //day of the year
{
dtData.DayOfYear = ReadFieldNumber(sbInput, fieldinfo);
}
break;
case 'D':
{
if( !StringToRead(fieldinfo.mModifier) )
{
dtData.Day = ReadFieldNumber(sbInput, fieldinfo);
}
}
break;
case 'M':
{
if( !StringToRead(fieldinfo.mModifier) )
{
dtData.Month = ReadFieldNumber(sbInput, fieldinfo);
}
else
{
String sMonth = ReadStringUntil( sbInput, fieldinfo.mMaxWidth, cNext);
//find the month from the table
int i = 0;
int nMax = fieldinfo.mMaxWidth == 0 ? sMonth.length() : fieldinfo.mMaxWidth;
while( i < MonthNames.length
&& !sMonth.equalsIgnoreCase(
MonthNames[i].substring(
0,
nMax > MonthNames[i].length() ? MonthNames[i].length() : nMax
)
)
) i++;
dtData.Month = i + 1;
}
if( dtData.Month > 12)
{
throw new IllegalArgumentException( "Pattern component '" + fieldinfo.mComponent + "' doesn't match! Unable to read: '" + sInputBackup + "'");
}
}
break;
case 'Y':
{
dtData.Year = ReadFieldNumber(sbInput, fieldinfo);
if( fieldinfo.mMaxWidth == 2)
{
//change this in the year 2050;
if( dtData.Year > 50)
dtData.Year += 1900;
else
dtData.Year += 2000;
}
}
break;
case 'P':
{
String sPM = ReadStringUntil( sbInput, 4, (char)0);
dtData.Hour += sPM.equalsIgnoreCase( "p.m.") && dtData.Hour != 12 ? 12 : 0;
}
break;
case 'h':
case 'H':
{
dtData.Hour = ReadFieldNumber(sbInput, fieldinfo);
}
break;
case 'm':
{
dtData.Minute = ReadFieldNumber(sbInput, fieldinfo);
}
break;
case 's':
{
dtData.Second = ReadFieldNumber(sbInput, fieldinfo);
}
break;
case 'f':
{
SizeNumber sn = ReadNumberWithSize(sbInput, fieldinfo.mMaxWidth);
dtData.MilliSecond = sn.number / Math.pow( 10.0f, sn.size);
}
break;
case 'z':
{
if( sbInput.toString().startsWith( "GMT" ) )
sbInput.delete(0, 3);
else
throw new IllegalArgumentException( "Pattern component '" + fieldinfo.mComponent + "' doesn't match! Unable to read: '" + sbInput + "'");
}
case 'Z':
{
int nMinus = 1;
if( sbInput.charAt(0) == '-' )
nMinus = -1;
sbInput.deleteCharAt(0);
int nHour = ReadNumber(sbInput, 2);
if( sbInput.charAt(0) != ':' )
{
//error
throw new IllegalArgumentException( "Pattern component '" + fieldinfo.mComponent + "' doesn't match! Unable to read: '" + sbInput + "'");
}
else
sbInput.deleteCharAt(0);
int nMinutes = ReadNumber(sbInput, 2);
dtData.TimeZone = (nHour * 60 + nMinutes) * nMinus;
}
break;
case 'i':
case 'I':
{
ReadStringUntil(sbInput, fieldinfo.mMaxWidth, cNext);
}
break;
default:
throw new IllegalArgumentException( "Unknown component specifier: '" + fieldinfo.mComponent + "'");
}
}
private int monthStart[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
private int monthStartLeap[] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
private String[] DayNames = {
"",
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
private String[] MonthNames = {
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
protected enum ParseState {
NORMAL,
INFIELD
}
protected enum ArgumentState {
COMPONENT,
FORMAT,
WIDTH
}
private class FieldInfo {
public char mComponent;
public String mModifier;
public String mWidth;
public int mMinWidth;
public int mMaxWidth;
public FieldInfo() {
reset();
}
public void reset() {
mComponent = 0;
mModifier = "";
mWidth = "";
mMinWidth = 0;
mMaxWidth = 0;
}
public boolean Analyze() {
int minusPos = mWidth.indexOf( '-' );
if( minusPos == -1 )
{
try {
mMinWidth = Integer.parseInt( mWidth );
}
catch (NumberFormatException e) {
mMinWidth = 0;
}
}
else
{
try {
mMinWidth = Integer.parseInt( mWidth.substring(0, minusPos) );
}
catch (NumberFormatException e) {
mMinWidth = 0;
}
try {
mMaxWidth = Integer.parseInt( mWidth.substring( minusPos + 1 ) );
}
catch (NumberFormatException e) {
mMaxWidth = 0;
}
}
return true;
}
}
class DateTimeData
{
public DateTimeData() {
Day = 1;
Month = 1;
Year = 0;
Hour = 0;
Minute = 0;
Second = 0;
TimeZone = com.altova.types.CalendarBase.TZ_MISSING;
DayOfYear = 0;
}
int Day;
int Month;
int Year;
int Hour;
int Minute;
int Second;
double MilliSecond;
int TimeZone;
int DayOfYear; //this value is stored for later processing
};
private String mPattern;
private char mFieldOpen;
private char mFieldClose;
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy