Last active
February 19, 2021 10:01
-
-
Save ipcjs/086e6c07ae0d95d67945355362687bf8 to your computer and use it in GitHub Desktop.
SimpleDateFormat is used to format/parse simple patterns.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:intl/intl.dart'; | |
/// @see: | |
/// - [intl/#83](https://github.com/dart-lang/intl/issues/83) | |
/// - [intl/#112](https://github.com/dart-lang/intl/issues/112) | |
/// - [DateFormat] | |
/// Created by ipcjs on 2021/2/19. | |
class SimpleDateFormat { | |
SimpleDateFormat(this.pattern) : assert(pattern.isNotEmpty); | |
final String pattern; | |
List<_Field> _fieldsPrivate; | |
List<_Field> get _fields => _fieldsPrivate ??= _parsePattern(pattern); | |
List<_Field> _parsePattern(String pattern) { | |
assert(pattern.isNotEmpty); | |
final fields = <_Field>[]; | |
var startIndex = 0; | |
var prevChar = pattern[startIndex]; | |
for (var i = startIndex + 1; i < pattern.length; i++) { | |
final char = pattern[i]; | |
if (char != prevChar) { | |
fields.add(_Field(pattern.substring(startIndex, i))); | |
startIndex = i; | |
} | |
prevChar = char; | |
} | |
fields.add(_Field(pattern.substring(startIndex))); | |
return fields; | |
} | |
/// @see [DateFormat.format] | |
String format(DateTime date) { | |
final sb = StringBuffer(); | |
for (final field in _fields) { | |
sb.write(field.format(date)); | |
} | |
return sb.toString(); | |
} | |
/// @see [DateFormat.parse] | |
DateTime parse(String string, [bool utc = false]) { | |
final reader = _StringReader(string); | |
final builder = _DateTimeBuilder()..utc = utc; | |
for (final field in _fields) { | |
field.parse(reader, builder); | |
} | |
return builder.build(); | |
} | |
@override | |
String toString() => 'SimpleDateFormat{pattern: $pattern, fields: $_fields}'; | |
} | |
/// @see [_DateFormatField] | |
class _Field { | |
_Field(this.pattern); | |
final String pattern; | |
int get width => pattern.length; | |
String _padInt(int v) => v.toString().padLeft(width, '0'); | |
String format(DateTime date) { | |
switch (pattern[0]) { | |
case 'y': | |
return _padInt(date.year); | |
case 'M': | |
return _padInt(date.month); | |
case 'd': | |
return _padInt(date.day); | |
case 'H': | |
return _padInt(date.hour); | |
case 'm': | |
return _padInt(date.minute); | |
case 's': | |
return _padInt(date.second); | |
default: | |
return pattern; | |
} | |
} | |
int _readInt(_StringReader reader) => int.tryParse(reader.read(width)) ?? throwFormatException(reader); | |
void parse(_StringReader reader, _DateTimeBuilder builder) { | |
switch (pattern[0]) { | |
case 'y': | |
builder.year = _readInt(reader); | |
break; | |
case 'M': | |
builder.month = _readInt(reader); | |
break; | |
case 'd': | |
builder.day = _readInt(reader); | |
break; | |
case 'H': | |
builder.hour = _readInt(reader); | |
break; | |
case 'm': | |
builder.minute = _readInt(reader); | |
break; | |
case 's': | |
builder.second = _readInt(reader); | |
break; | |
default: | |
reader.skip(width); | |
break; | |
} | |
} | |
int /*Never*/ throwFormatException(_StringReader reader) { | |
throw FormatException('Trying to read $this from ${reader.contents} at position ${reader.index}'); | |
} | |
@override | |
String toString() => pattern; | |
} | |
/// @see [IntlStream] | |
class _StringReader { | |
_StringReader(this.contents); | |
final String contents; | |
int index = 0; | |
String read(int width) { | |
final substring = contents.substring(index, index + width); | |
index += width; | |
return substring; | |
} | |
void skip(int width) { | |
index += width; | |
} | |
} | |
/// @see [DateBuilder] | |
class _DateTimeBuilder { | |
int year; | |
int month = 1; | |
int day = 1; | |
int hour = 0; | |
int minute = 0; | |
int second = 0; | |
int millisecond = 0; | |
int microsecond = 0; | |
bool utc = false; | |
DateTime build() => utc | |
? DateTime.utc(year, month, day, hour, minute, second, millisecond, microsecond) | |
: DateTime(year, month, day, hour, minute, second, millisecond, microsecond); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment