Further progress on SimpleDateFormat

This commit is contained in:
konsoletyper 2014-06-23 17:41:07 +04:00
parent c0909c7cce
commit 2127ae4280
3 changed files with 294 additions and 0 deletions

View File

@ -16,6 +16,7 @@
package org.teavm.classlib.java.text;
import org.teavm.classlib.java.util.TCalendar;
import org.teavm.classlib.java.util.TGregorianCalendar;
/**
*
@ -157,4 +158,122 @@ abstract class DateFormatElement {
}
}
}
public static class Numeric extends DateFormatElement {
private int field;
private int length;
private int offset;
public Numeric(int field, int length, int offset) {
this.field = field;
this.length = length;
this.offset = offset;
}
@Override
public void format(TCalendar date, StringBuffer buffer) {
int number = date.get(field) + offset;
String str = Integer.toString(number);
for (int i = str.length(); i < length; ++i) {
buffer.append('0');
}
buffer.append(str);
}
@Override
public void parse(String text, TCalendar date, TParsePosition position) {
int num = 0;
int i = 0;
int pos = position.getIndex();
while (position.getIndex() < text.length() && i < length) {
char c = text.charAt(pos);
if (c >= '0' && c <= '9') {
num = num * 10 + (c - '0');
++pos;
++i;
} else {
break;
}
}
if (i == 0) {
position.setErrorIndex(position.getIndex());
return;
}
position.setIndex(pos);
date.set(field, num - offset);
}
}
public static class Year extends DateFormatElement {
private int field;
public Year(int field) {
this.field = field;
}
@Override
public void format(TCalendar date, StringBuffer buffer) {
int number = date.get(field);
if (number < 10) {
buffer.append(number);
} else {
buffer.append((char)((number % 100 / 10) + '0'));
buffer.append((char)((number % 10) + '0'));
}
}
@Override
public void parse(String text, TCalendar date, TParsePosition position) {
int num = 0;
int pos = position.getIndex();
char c = text.charAt(pos++);
if (c < '0' || c > '9') {
position.setErrorIndex(position.getErrorIndex());
return;
}
num = c - '0';
c = text.charAt(pos);
if (c >= '0' && c <= '9') {
num = num * 10 + (c - '0');
++pos;
}
position.setIndex(pos);
TCalendar calendar = new TGregorianCalendar();
int currentYear = calendar.get(TCalendar.YEAR);
int currentShortYear = currentYear % 100;
int century = currentYear / 100;
if (currentShortYear > 80) {
if (num < currentShortYear - 80) {
century++;
}
} else {
if (num > currentShortYear + 20) {
--century;
}
}
date.set(field, num + century * 100);
}
}
public static class ConstantText extends DateFormatElement {
private String textConstant;
public ConstantText(String textConstant) {
this.textConstant = textConstant;
}
@Override
public void format(TCalendar date, StringBuffer buffer) {
buffer.append(textConstant);
}
@Override
public void parse(String text, TCalendar date, TParsePosition position) {
if (matches(text, position.getIndex(), textConstant)) {
position.setIndex(position.getIndex() + textConstant.length());
} else {
position.setErrorIndex(position.getIndex());
}
}
}
}

View File

@ -0,0 +1,120 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed 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.
*/
package org.teavm.classlib.java.text;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author Alexey Andreev
*/
class SimpleDatePatternParser {
private TDateFormatSymbols symbols;
private List<DateFormatElement> elements = new ArrayList<>();
private int index;
private String pattern;
public SimpleDatePatternParser(TDateFormatSymbols symbols) {
this.symbols = symbols;
}
public void parsePattern(String pattern) {
this.pattern = pattern;
for (index = 0; index < pattern.length(); ++index) {
char c = pattern.charAt(index);
switch (c) {
case '\'': {
++index;
parseQuoted();
break;
}
case 'G':
parseRepetitions();
elements.add(new DateFormatElement.EraText(symbols));
break;
case 'y':
break;
default: {
StringBuilder sb = new StringBuilder();
while (index < pattern.length() && isControl(pattern.charAt(index))) {
sb.append(pattern.charAt(index++));
}
break;
}
}
}
}
private boolean isControl(char c) {
switch (c) {
case '\'':
case 'G':
case 'y':
case 'Y':
case 'M':
case 'w':
case 'W':
case 'D':
case 'd':
case 'F':
case 'E':
case 'u':
case 'a':
case 'H':
case 'k':
case 'K':
case 'h':
case 'm':
case 's':
case 'S':
case 'z':
case 'Z':
case 'X':
return true;
default:
return false;
}
}
private void parseQuoted() {
StringBuilder sb = new StringBuilder();
while (index < pattern.length()) {
char c = pattern.charAt(index++);
if (c == '\'') {
if (index < pattern.length() && pattern.charAt(index) == '\'') {
sb.append('\'');
++index;
} else {
break;
}
} else {
sb.append(c);
}
}
elements.add(new DateFormatElement.ConstantText(sb.toString()));
}
private int parseRepetitions() {
int count = 1;
char orig = pattern.charAt(index++);
while (index < pattern.length() && pattern.charAt(index) == orig) {
++index;
++count;
}
return count;
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed 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.
*/
package org.teavm.classlib.java.text;
import org.teavm.classlib.java.util.TCalendar;
import org.teavm.classlib.java.util.TDate;
import org.teavm.classlib.java.util.TGregorianCalendar;
/**
*
* @author Alexey Andreev
*/
public class TSimpleDateFormat extends TDateFormat {
private DateFormatElement[] elements;
@Override
public StringBuffer format(TDate date, StringBuffer buffer, TFieldPosition field) {
TCalendar calendar = new TGregorianCalendar();
calendar.setTime(date);
for (DateFormatElement element : elements) {
element.format(calendar, buffer);
}
return buffer;
}
@Override
public TDate parse(String string, TParsePosition position) {
TCalendar calendar = new TGregorianCalendar();
calendar.set(0, 0, 0, 0, 0, 0);
for (DateFormatElement element : elements) {
if (position.getIndex() > string.length()) {
position.setErrorIndex(position.getErrorIndex());
return null;
}
element.parse(string, calendar, position);
if (position.getErrorIndex() >= 0) {
return null;
}
}
return calendar.getTime();
}
}