changes as per review
diff --git a/benchmark/fixed_datetime_formatter_benchmark.dart b/benchmark/fixed_datetime_formatter_benchmark.dart
index 7ac4a2b..89b34a1 100644
--- a/benchmark/fixed_datetime_formatter_benchmark.dart
+++ b/benchmark/fixed_datetime_formatter_benchmark.dart
@@ -8,10 +8,10 @@
 /// This class tests the implementation speed of
 /// _DateFormatPatternField::nextInteger, which is assumed to be called often and
 /// thus being performance-critical.
-class NewMethod extends BenchmarkBase {
+class DecodeBenchmark extends BenchmarkBase {
   late String result;
   late FixedDateTimeFormatter fixedDateTimeFormatter;
-  NewMethod() : super('Parse a million strings to datetime');
+  DecodeBenchmark() : super('Parse a million strings to datetime');
 
   @override
   void setup() {
@@ -27,5 +27,5 @@
 }
 
 void main() {
-  NewMethod().report();
+  DecodeBenchmark().report();
 }
diff --git a/lib/src/fixed_datetime_formatter.dart b/lib/src/fixed_datetime_formatter.dart
index d1bd7cb..04b9700 100644
--- a/lib/src/fixed_datetime_formatter.dart
+++ b/lib/src/fixed_datetime_formatter.dart
@@ -9,15 +9,15 @@
 /// the same result as calling `DateTime(1996, 4, 25, 5, 3, 22)`.
 ///
 /// The allowed characters are
-/// * `Y`	a digit used in the time scale component “calendar year”
-/// * `M`	a digit used in the time scale component “calendar month”
-/// * `D`	a digit used in the time scale component “calendar day”
-/// * `E`	a digit used in the time scale component “decade”
-/// * `C`	a digit used in the time scale component “century”
-/// * `h`	a digit used in the time scale component “clock hour”
-/// * `m`	a digit used in the time scale component “clock minute”
-/// * `s`	a digit used in the time scale component “clock second”
-/// as specified in the ISO 8601 standard.
+/// * `Y`	for “calendar year”
+/// * `M`	for “calendar month”
+/// * `D`	for “calendar day”
+/// * `E`	for “decade”
+/// * `C`	for “century”
+/// * `h`	for “clock hour”
+/// * `m`	for “clock minute”
+/// * `s`	for “clock second”
+/// * `S`	for “fractional clock second”
 ///
 /// Non-allowed characters in the format [pattern] are ignored when decoding a
 /// string, in this case `YYYY kiwi MM` is the same format string as
@@ -33,29 +33,46 @@
 /// containing delimiters, as the parser would not know how many digits to take
 /// otherwise.
 class FixedDateTimeFormatter {
-  static final _validFormatCharacters = 'YMDEChms'.codeUnits;
-  static final yearCode = 'Y'.codeUnitAt(0);
-  static final monthCode = 'M'.codeUnitAt(0);
-  static final dayCode = 'D'.codeUnitAt(0);
-  static final decadeCode = 'E'.codeUnitAt(0);
-  static final centuryCode = 'C'.codeUnitAt(0);
-  static final hourCode = 'h'.codeUnitAt(0);
-  static final minuteCode = 'm'.codeUnitAt(0);
-  static final secondCode = 's'.codeUnitAt(0);
+  static const _powersOfTen = [0, 1, 10, 100, 1000, 10000, 100000];
+  static const _validFormatCharacters = [
+    _yearCode,
+    _monthCode,
+    _dayCode,
+    _decadeCode,
+    _centuryCode,
+    _hourCode,
+    _minuteCode,
+    _secondCode,
+    _fractionSecondCode,
+  ];
+  static const _yearCode = 0x59; /*Y*/
+  static const _monthCode = 0x4D; /*M*/
+  static const _dayCode = 0x44; /*D*/
+  static const _decadeCode = 0x45; /*E*/
+  static const _centuryCode = 0x43; /*C*/
+  static const _hourCode = 0x68; /*H*/
+  static const _minuteCode = 0x6D; /*m*/
+  static const _secondCode = 0x73; /*s*/
+  static const _fractionSecondCode = 0x53; /*S*/
 
+  ///Store publicly in case the user wants to retrieve it
   final String pattern;
+
+  ///Whether to use UTC or the local time zone
+  final bool isUtc;
   final _blocks = _ParsedFormatBlocks();
 
   /// Creates a new [FixedDateTimeFormatter] with the provided [pattern].
   ///
   /// The [pattern] interprets the characters mentioned in
   /// [FixedDateTimeFormatter] to represent fields of a `DateTime` value. Other
-  /// characters are not special.
+  /// characters are not special. If [isUtc] is set to false, the DateTime is
+  /// constructed with respect to the local timezone.
   ///
   /// There must at most be one sequence of each special character to ensure a
   /// single source of truth when constructing the [DateTime], so a pattern of
   /// `"CCCC-MM-DD, CC"` is invalid, because it has two separate `C` sequences.
-  FixedDateTimeFormatter(this.pattern) {
+  FixedDateTimeFormatter(this.pattern, {this.isUtc = true}) {
     int? current;
     var start = 0;
     var characters = pattern.codeUnits;
@@ -95,12 +112,18 @@
       if (previousEnd < start) {
         buffer.write(pattern.substring(previousEnd, start));
       }
+      var formatCharacter = _blocks.formatCharacters[i];
       var number = _extractNumFromDateTime(
-        _blocks.formatCharacters[i],
+        formatCharacter,
         datetime,
       ).toString();
       if (number.length > length) {
-        number = number.substring(number.length - length);
+        if (formatCharacter == _fractionSecondCode) {
+          //Special case, as we want fractional seconds to be the leading digits
+          number = number.substring(length);
+        } else {
+          number = number.substring(number.length - length);
+        }
       } else if (number.length < length) {
         number = number.padLeft(length, '0');
       }
@@ -115,23 +138,26 @@
     return buffer.toString();
   }
 
-  int _extractNumFromDateTime(int? formatChar, DateTime dt) {
-    if (formatChar == yearCode) {
-      return dt.year;
-    } else if (formatChar == centuryCode) {
-      return (dt.year / 100).floor();
-    } else if (formatChar == decadeCode) {
-      return (dt.year / 10).floor();
-    } else if (formatChar == monthCode) {
-      return dt.month;
-    } else if (formatChar == dayCode) {
-      return dt.day;
-    } else if (formatChar == hourCode) {
-      return dt.hour;
-    } else if (formatChar == minuteCode) {
-      return dt.minute;
-    } else if (formatChar == secondCode) {
-      return dt.second;
+  int _extractNumFromDateTime(int? formatChar, DateTime dateTime) {
+    switch (formatChar) {
+      case _yearCode:
+        return dateTime.year;
+      case _centuryCode:
+        return (dateTime.year / 100).floor();
+      case _decadeCode:
+        return (dateTime.year / 10).floor();
+      case _monthCode:
+        return dateTime.month;
+      case _dayCode:
+        return dateTime.day;
+      case _hourCode:
+        return dateTime.hour;
+      case _minuteCode:
+        return dateTime.minute;
+      case _secondCode:
+        return dateTime.second;
+      case _fractionSecondCode:
+        return dateTime.microsecond;
     }
     throw AssertionError("Unreachable, the key is checked in the constructor");
   }
@@ -139,13 +165,13 @@
   /// Parse a string [formattedDateTime] to a local [DateTime] as specified in the
   /// [pattern], substituting missing values with a default. Throws an exception
   /// on failure to parse.
-  DateTime decode(String formattedDateTime, {bool isUtc = false}) {
+  DateTime decode(String formattedDateTime) {
     return _decode(formattedDateTime, isUtc, true);
   }
 
   /// Same as [decode], but will not throw on parsing erros, instead using
   /// the default value as if the format char was not present in the [pattern].
-  DateTime tryDecode(String formattedDateTime, {bool isUtc = false}) {
+  DateTime tryDecode(String formattedDateTime) {
     return _decode(formattedDateTime, isUtc, false);
   }
 
@@ -163,41 +189,83 @@
     var hour = 0;
     var minute = 0;
     var second = 0;
+    var microsecond = 0;
     for (int i = 0; i < _blocks.length; i++) {
       var char = _blocks.formatCharacters[i];
-      var num = _extractNumFromString(characters, i, throwOnError);
-      if (num != null) {
-        if (char == yearCode) {
-          year = num;
-        } else if (char == centuryCode) {
-          century = num;
-        } else if (char == decadeCode) {
-          decade = num;
-        } else if (char == monthCode) {
-          month = num;
-        } else if (char == dayCode) {
-          day = num;
-        } else if (char == hourCode) {
-          hour = num;
-        } else if (char == minuteCode) {
-          minute = num;
-        } else if (char == secondCode) {
-          second = num;
+      var number = _extractNumFromString(characters, i, throwOnError);
+      if (number != null) {
+        if (char == _fractionSecondCode) {
+          //Special case, as we want fractional seconds to be the leading digits
+          var numberLength = _blocks.ends[i] - _blocks.starts[i];
+          number *= _powersOfTen[6 - numberLength + 1];
+        }
+        switch (char) {
+          case _yearCode:
+            year = number;
+            break;
+          case _centuryCode:
+            century = number;
+            break;
+          case _decadeCode:
+            decade = number;
+            break;
+          case _monthCode:
+            month = number;
+            break;
+          case _dayCode:
+            day = number;
+            break;
+          case _hourCode:
+            hour = number;
+            break;
+          case _minuteCode:
+            minute = number;
+            break;
+          case _secondCode:
+            second = number;
+            break;
+          case _fractionSecondCode:
+            microsecond = number;
+            break;
         }
       }
     }
     var totalYear = year + 100 * century + 10 * decade;
     if (isUtc) {
-      return DateTime.utc(totalYear, month, day, hour, minute, second, 0, 0);
+      return DateTime.utc(
+        totalYear,
+        month,
+        day,
+        hour,
+        minute,
+        second,
+        0,
+        microsecond,
+      );
     } else {
-      return DateTime(totalYear, month, day, hour, minute, second, 0, 0);
+      return DateTime(
+        totalYear,
+        month,
+        day,
+        hour,
+        minute,
+        second,
+        0,
+        microsecond,
+      );
     }
   }
 
   int? _extractNumFromString(
-      List<int> characters, int index, bool throwOnError) {
-    var parsed =
-        tryParse(characters, _blocks.starts[index], _blocks.ends[index]);
+    List<int> characters,
+    int index,
+    bool throwOnError,
+  ) {
+    var parsed = tryParse(
+      characters,
+      _blocks.starts[index],
+      _blocks.ends[index],
+    );
     if (parsed == null && throwOnError) {
       throw FormatException(
           '${String.fromCharCodes(characters)} should only contain digits');
@@ -205,13 +273,12 @@
     return parsed;
   }
 
-  static final zeroCode = '0'.codeUnitAt(0);
   int? tryParse(List<int> characters, int start, int end) {
     int result = 0;
     for (var i = start; i < end; i++) {
-      var character = characters[i];
-      if (character >= zeroCode && character < zeroCode + 10) {
-        result = result * 10 + (character - zeroCode);
+      var digit = characters[i] ^ 0x30;
+      if (digit <= 9) {
+        result = result * 10 + digit;
       } else {
         return null;
       }
diff --git a/test/fixed_datetime_formatter_test.dart b/test/fixed_datetime_formatter_test.dart
index 2dd883a..7c7f0a5 100644
--- a/test/fixed_datetime_formatter_test.dart
+++ b/test/fixed_datetime_formatter_test.dart
@@ -9,40 +9,60 @@
   //decode
   test('Parse only year', () {
     var time = FixedDateTimeFormatter('YYYY').decode('1996');
-    expect(time, DateTime(1996));
+    expect(time, DateTime.utc(1996));
   });
   test('Escaped chars are ignored', () {
     var time = FixedDateTimeFormatter('YYYY kiwi MM').decode('1996 rnad 01');
-    expect(time, DateTime(1996, 1));
+    expect(time, DateTime.utc(1996, 1));
   });
   test('Parse two years throws', () {
     expect(() => FixedDateTimeFormatter('YYYY YYYY'), throwsException);
   });
   test('Parse year and century', () {
     var time = FixedDateTimeFormatter('CCYY').decode('1996');
-    expect(time, DateTime(1996));
+    expect(time, DateTime.utc(1996));
   });
   test('Parse year, decade and century', () {
     var time = FixedDateTimeFormatter('CCEY').decode('1996');
-    expect(time, DateTime(1996));
+    expect(time, DateTime.utc(1996));
   });
   test('Parse year, century, month', () {
     var time = FixedDateTimeFormatter('CCYY MM').decode('1996 04');
-    expect(time, DateTime(1996, 4));
+    expect(time, DateTime.utc(1996, 4));
   });
   test('Parse year, century, month, day', () {
     var time = FixedDateTimeFormatter('CCYY MM-DD').decode('1996 04-25');
-    expect(time, DateTime(1996, 4, 25));
+    expect(time, DateTime.utc(1996, 4, 25));
   });
   test('Parse year, century, month, day, hour, minute, second', () {
     var time = FixedDateTimeFormatter('CCYY MM-DD hh:mm:ss')
         .decode('1996 04-25 05:03:22');
-    expect(time, DateTime(1996, 4, 25, 5, 3, 22));
+    expect(time, DateTime.utc(1996, 4, 25, 5, 3, 22));
   });
-  test('Parse YYYYMMDDhhmmss', () {
+  test('Parse YYYYMMDDhhmmssSSS', () {
     var time =
-        FixedDateTimeFormatter('YYYYMMDDhhmmss').decode('19960425050322');
-    expect(time, DateTime(1996, 4, 25, 5, 3, 22));
+        FixedDateTimeFormatter('YYYYMMDDhhmmssSSS').decode('19960425050322533');
+    expect(time, DateTime.utc(1996, 4, 25, 5, 3, 22, 533));
+  });
+  test('Parse S', () {
+    var time = FixedDateTimeFormatter('S').decode('1');
+    expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 100, 0));
+  });
+  test('Parse SS', () {
+    var time = FixedDateTimeFormatter('SS').decode('01');
+    expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 10, 0));
+  });
+  test('Parse SSS', () {
+    var time = FixedDateTimeFormatter('SSS').decode('001');
+    expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 1, 0));
+  });
+  test('Parse SSSSSS', () {
+    var time = FixedDateTimeFormatter('SSSSSS').decode('000001');
+    expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 0, 1));
+  });
+  test('Parse SSSSSS 2', () {
+    var time = FixedDateTimeFormatter('SSSSSS').decode('001000');
+    expect(time, DateTime.utc(0, 1, 1, 0, 0, 0, 1, 0));
   });
   test('Parse hex year throws', () {
     expect(
@@ -53,32 +73,32 @@
   //tryDecode
   test('Try parse year', () {
     var time = FixedDateTimeFormatter('YYYY').tryDecode('1996');
-    expect(time, DateTime(1996));
+    expect(time, DateTime.utc(1996));
   });
   test('Try parse hex year return default', () {
     var time = FixedDateTimeFormatter('YYYY').tryDecode('0xAB');
-    expect(time, DateTime(0));
+    expect(time, DateTime.utc(0));
   });
   test('Try parse invalid returns default', () {
     var time = FixedDateTimeFormatter('YYYY').tryDecode('1x96');
-    expect(time, DateTime(0));
+    expect(time, DateTime.utc(0));
   });
   //encode
   test('Format simple', () {
-    var time = DateTime(1996, 1);
+    var time = DateTime.utc(1996, 1);
     expect('1996 kiwi 01', FixedDateTimeFormatter('YYYY kiwi MM').encode(time));
   });
   test('Format YYYYMMDDhhmmss', () {
     var str = FixedDateTimeFormatter('YYYYMMDDhhmmss')
-        .encode(DateTime(1996, 4, 25, 5, 3, 22));
+        .encode(DateTime.utc(1996, 4, 25, 5, 3, 22));
     expect('19960425050322', str);
   });
   test('Format CCEY-MM', () {
-    var str = FixedDateTimeFormatter('CCEY-MM').encode(DateTime(1996, 4));
+    var str = FixedDateTimeFormatter('CCEY-MM').encode(DateTime.utc(1996, 4));
     expect('1996-04', str);
   });
   test('Format XCCEY-MMX', () {
-    var str = FixedDateTimeFormatter('XCCEY-MMX').encode(DateTime(1996, 4));
+    var str = FixedDateTimeFormatter('XCCEY-MMX').encode(DateTime.utc(1996, 4));
     expect('X1996-04X', str);
   });
 }