どのパターンか判断できるようにしてみた。Ideone.com - vcrHk5 - Online C# Compiler & Debugging Tool
using System; using System.Collections.Generic; using System.Diagnostics; using System.Text; namespace Automaton { class Program { const string INDENT = "\t"; static void Main(string[] args) { DateTimeChecker checker = new DateTimeChecker(); List<Tuple<string, DateTimeChecker.Formats>> testCase = new List<Tuple<string, DateTimeChecker.Formats>>(); testCase.Add(Tuple.Create("2018/11/16 12:34:56.789", DateTimeChecker.Formats.yyyyMMddHHmmssfff)); testCase.Add(Tuple.Create("2018/11/16 12:34:56.78", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/11/16 12:34:56.7", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/11/16 12:34:56.", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/11/16 12:34:56", DateTimeChecker.Formats.yyyyMMddHHmmss)); testCase.Add(Tuple.Create("2018/11/16 12:34:5", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/11/16 12:34:", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/11/16 12:34", DateTimeChecker.Formats.yyyyMMddHHmm)); testCase.Add(Tuple.Create("2018/11/16 12:3", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/11/16 12:", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/11/16 12", DateTimeChecker.Formats.yyyyMMddHH)); testCase.Add(Tuple.Create("2018/11/16 1", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/11/16 ", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/11/16", DateTimeChecker.Formats.yyyyMMdd)); testCase.Add(Tuple.Create("2018/11/1", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/11/", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/11", DateTimeChecker.Formats.yyyyMM)); testCase.Add(Tuple.Create("2018/1", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018/", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2018", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("201", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("20", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("2", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("", DateTimeChecker.Formats.None)); TestDateTime(checker, testCase); checker.Reset(); testCase.Clear(); testCase.Add(Tuple.Create("18/11/16 12:34:56.789", DateTimeChecker.Formats.yyMMddHHmmssfff)); testCase.Add(Tuple.Create("18/11/16 12:34:56.78", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/11/16 12:34:56.7", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/11/16 12:34:56.", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/11/16 12:34:56", DateTimeChecker.Formats.yyMMddHHmmss)); testCase.Add(Tuple.Create("18/11/16 12:34:5", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/11/16 12:34:", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/11/16 12:34", DateTimeChecker.Formats.yyMMddHHmm)); testCase.Add(Tuple.Create("18/11/16 12:3", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/11/16 12:", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/11/16 12", DateTimeChecker.Formats.yyMMddHH)); testCase.Add(Tuple.Create("18/11/16 1", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/11/16 ", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/11/16", DateTimeChecker.Formats.yyMMdd)); testCase.Add(Tuple.Create("18/11/1", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/11/", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/11", DateTimeChecker.Formats.MMdd)); testCase.Add(Tuple.Create("18/1", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18/", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("18", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("1", DateTimeChecker.Formats.None)); TestDateTime(checker, testCase); checker.Reset(); testCase.Clear(); testCase.Add(Tuple.Create("11/16 12:34:56.789", DateTimeChecker.Formats.MMddHHmmssfff)); testCase.Add(Tuple.Create("11/16 12:34:56.78", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("11/16 12:34:56.7", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("11/16 12:34:56.", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("11/16 12:34:56", DateTimeChecker.Formats.MMddHHmmss)); testCase.Add(Tuple.Create("11/16 12:34:5", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("11/16 12:34:", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("11/16 12:34", DateTimeChecker.Formats.MMddHHmm)); testCase.Add(Tuple.Create("11/16 12:3", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("11/16 12:", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("11/16 12", DateTimeChecker.Formats.MMddHH)); testCase.Add(Tuple.Create("11/16 1", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("11/16 ", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("11/16", DateTimeChecker.Formats.MMdd)); testCase.Add(Tuple.Create("11/1", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("11/", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("11", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("1", DateTimeChecker.Formats.None)); TestDateTime(checker, testCase); checker.Reset(); testCase.Clear(); testCase.Add(Tuple.Create("12:34:56.789", DateTimeChecker.Formats.HHmmssfff)); testCase.Add(Tuple.Create("12:34:56.78", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("12:34:56.7", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("12:34:56.", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("12:34:56", DateTimeChecker.Formats.HHmmss)); testCase.Add(Tuple.Create("12:34:5", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("12:34:", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("12:34", DateTimeChecker.Formats.HHmm)); testCase.Add(Tuple.Create("12:3", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("12:", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("12", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("1", DateTimeChecker.Formats.None)); TestDateTime(checker, testCase); checker.Reset(); testCase.Clear(); testCase.Add(Tuple.Create("34:56.789", DateTimeChecker.Formats.mmssfff)); testCase.Add(Tuple.Create("34:56.78", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("34:56.7", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("34:56.", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("34:56", DateTimeChecker.Formats.HHmm)); testCase.Add(Tuple.Create("34:5", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("34:", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("34", DateTimeChecker.Formats.None)); testCase.Add(Tuple.Create("3", DateTimeChecker.Formats.None)); TestDateTime(checker, testCase); checker.Reset(); testCase.Clear(); } static void TestDateTime(DateTimeChecker checker, IList<Tuple<string, DateTimeChecker.Formats>> testCase) { foreach (Tuple<string, DateTimeChecker.Formats> t in testCase) { Console.Write("[" + t.Item1 + "] "); checker.Reset(); foreach (char ch in t.Item1) { checker.MoveNext(ch); if (checker.IsError()) { Console.Write(INDENT); Console.WriteLine(":ERROR"); Debug.Assert(checker.Format == t.Item2, "asersion failed!!"); break; } } if (!checker.IsError()) { if (checker.IsAcceptable()) { Console.Write(INDENT); Console.Write(":OK"); Console.Write(INDENT); Console.WriteLine(checker.Format); Debug.Assert(checker.Format == t.Item2, t.Item1 + " asersion failed!!"); } else { Console.Write(INDENT); Console.WriteLine(":NG"); Debug.Assert(checker.Format == t.Item2, "asersion failed!!"); } } } } } interface Checker { void Reset(); void MoveNext(char ch); bool IsAcceptable(); bool IsError(); bool IsNextError(char ch); string Current(); } class DateTimeChecker : Checker { /// <summary>formats for date or time</summary> public enum Formats { /// <summary>nether date nor time</summary> None, /// <summary>yyyy/MM/dd HH:mm:ss.fff</summary> yyyyMMddHHmmssfff, /// <summary>yyyy/MM/dd HH:mm:ss</summary> yyyyMMddHHmmss, /// <summary>yyyy/MM/dd HH:mm</summary> yyyyMMddHHmm, /// <summary>yyyy/MM/dd HH</summary> yyyyMMddHH, /// <summary>yyyy/MM/dd</summary> yyyyMMdd, /// <summary>yyyy/MM</summary> yyyyMM, /// <summary>yy/MM/dd HH:mm:ss.fff</summary> yyMMddHHmmssfff, /// <summary>yy/MM/dd HH:mm:ss</summary> yyMMddHHmmss, /// <summary>yy/MM/dd HH:mm</summary> yyMMddHHmm, /// <summary>yy/MM/dd HH</summary> yyMMddHH, /// <summary>yy/MM/dd</summary> yyMMdd, /// <summary>MM/dd HH:mm:ss.fff</summary> MMddHHmmssfff, /// <summary>MM/dd HH:mm:ss</summary> MMddHHmmss, /// <summary>MM/dd HH:mm</summary> MMddHHmm, /// <summary>MM/dd HH</summary> MMddHH, /// <summary>MM/dd</summary> MMdd, /// <summary>HH:mm:ss.fff</summary> HHmmssfff, /// <summary>HH:mm:ss</summary> HHmmss, /// <summary>HH:mm</summary> HHmm, /// <summary>mm:ss.fff</summary> mmssfff, } enum States { Error, State00, State01, State02, State03, State04, State05, State06, State07, State08, State09, State10, State11, State12, State13, State14, State15, State16, State17, State18, State19, State20, State21, State22, State23, State24, State25, State26, State27, State28, State29, } StringBuilder _sb; States _state; List<States> _breadcrumb; Formats _format; public Formats Format { get { return _format; } } public DateTimeChecker() { _sb = new StringBuilder(); _breadcrumb = new List<States>(); Reset(); } public void Reset() { _state = States.State00; _sb.Clear(); _breadcrumb.Clear(); _format = Formats.None; } public void MoveNext(char ch) { _sb.Append(ch); States oldState = _state; _state = GetNext(ch); JudgeFormat(); } void JudgeFormat() { if (_state == States.State17) { _format = Formats.yyyyMM; _breadcrumb.Add(_state); } else if (_state == States.State10) { _format = Formats.MMdd; _breadcrumb.Add(_state); } else if (_state == States.State11) { _format = Formats.HHmm; _breadcrumb.Add(_state); } else if (_state == States.State22) { // there are two ways to come here. if (_breadcrumb[_breadcrumb.Count - 1] == States.State17) { _format = Formats.yyyyMMdd; } else { _format = Formats.yyMMdd; } _breadcrumb.Add(_state); } else if (_state == States.State23) { // there are three ways to come here. if (_breadcrumb[_breadcrumb.Count - 1] == States.State10) { _format = Formats.MMddHH; } else if (_breadcrumb[_breadcrumb.Count - 2] == States.State10) { _format = Formats.yyMMddHH; } else { _format = Formats.yyyyMMddHH; } _breadcrumb.Add(_state); } else if (_state == States.State29) { // there are three ways to come here. if (_breadcrumb[_breadcrumb.Count - 2] == States.State10) { _format = Formats.MMddHHmm; } else if (_breadcrumb[_breadcrumb.Count - 3] == States.State10) { _format = Formats.yyMMddHHmm; } else { _format = Formats.yyyyMMddHHmm; } _breadcrumb.Add(_state); } else if (_state == States.State24) { // there are four ways to come here. if (_breadcrumb[_breadcrumb.Count - 1] == States.State11) { _format = Formats.HHmmss; } else if (_breadcrumb[_breadcrumb.Count - 3] == States.State10) { _format = Formats.MMddHHmmss; } else if (_breadcrumb[_breadcrumb.Count - 4] == States.State10) { _format = Formats.yyMMddHHmmss; } else { _format = Formats.yyyyMMddHHmmss; } _breadcrumb.Add(_state); } else if (_state == States.State27) { // there are five ways to come here. if (_breadcrumb[_breadcrumb.Count - 1] == States.State11) { _format = Formats.mmssfff; } else if (_breadcrumb[_breadcrumb.Count - 2] == States.State11) { _format = Formats.HHmmssfff; } else if (_breadcrumb[_breadcrumb.Count - 4] == States.State10) { _format = Formats.MMddHHmmssfff; } else if (_breadcrumb[_breadcrumb.Count - 5] == States.State10) { _format = Formats.yyMMddHHmmssfff; } else { _format = Formats.yyyyMMddHHmmssfff; } _breadcrumb.Add(_state); } else { _format = Formats.None; } } public bool IsAcceptable() { return _state == States.State10 || _state == States.State11 || _state == States.State17 || _state == States.State22 || _state == States.State23 || _state == States.State24 || _state == States.State27 || _state == States.State29; } public bool IsError() { return _state == States.Error; } public bool IsNextError(char ch) { States next = GetNext(ch); return IsError(next); } public string Current() { return _sb.ToString(); } States GetNext(char ch) { States next = States.Error; switch (_state) { case States.State00: next = Transition(ch, States.State01, States.Error, States.Error, States.Error, States.Error); break; case States.State01: next = Transition(ch, States.State02, States.Error, States.Error, States.Error, States.Error); break; case States.State02: next = Transition(ch, States.State03, States.State04, States.Error, States.State05, States.Error); break; case States.State03: next = Transition(ch, States.State06, States.Error, States.Error, States.Error, States.Error); break; case States.State04: next = Transition(ch, States.State07, States.Error, States.Error, States.Error, States.Error); break; case States.State05: next = Transition(ch, States.State08, States.Error, States.Error, States.Error, States.Error); break; case States.State06: next = Transition(ch, States.Error, States.State09, States.Error, States.Error, States.Error); break; case States.State07: next = Transition(ch, States.State10, States.Error, States.Error, States.Error, States.Error); break; case States.State08: next = Transition(ch, States.State11, States.Error, States.Error, States.Error, States.Error); break; case States.State09: next = Transition(ch, States.State12, States.Error, States.Error, States.Error, States.Error); break; case States.State10: next = Transition(ch, States.Error, States.State13, States.State14, States.Error, States.Error); break; case States.State11: next = Transition(ch, States.Error, States.Error, States.Error, States.State15, States.State16); break; case States.State12: next = Transition(ch, States.State17, States.Error, States.Error, States.Error, States.Error); break; case States.State13: next = Transition(ch, States.State18, States.Error, States.Error, States.Error, States.Error); break; case States.State14: next = Transition(ch, States.State19, States.Error, States.Error, States.Error, States.Error); break; case States.State15: next = Transition(ch, States.State20, States.Error, States.Error, States.Error, States.Error); break; case States.State16: next = Transition(ch, States.State21, States.Error, States.Error, States.Error, States.Error); break; case States.State17: next = Transition(ch, States.Error, States.State13, States.Error, States.Error, States.Error); break; case States.State18: next = Transition(ch, States.State22, States.Error, States.Error, States.Error, States.Error); break; case States.State19: next = Transition(ch, States.State23, States.Error, States.Error, States.Error, States.Error); break; case States.State20: next = Transition(ch, States.State24, States.Error, States.Error, States.Error, States.Error); break; case States.State21: next = Transition(ch, States.State25, States.Error, States.Error, States.Error, States.Error); break; case States.State22: next = Transition(ch, States.Error, States.Error, States.State14, States.Error, States.Error); break; case States.State23: next = Transition(ch, States.Error, States.Error, States.Error, States.State26, States.Error); break; case States.State24: next = Transition(ch, States.Error, States.Error, States.Error, States.Error, States.State16); break; case States.State25: next = Transition(ch, States.State27, States.Error, States.Error, States.Error, States.Error); break; case States.State26: next = Transition(ch, States.State28, States.Error, States.Error, States.Error, States.Error); break; case States.State27: next = Transition(ch, States.Error, States.Error, States.Error, States.Error, States.Error); break; case States.State28: next = Transition(ch, States.State29, States.Error, States.Error, States.Error, States.Error); break; case States.State29: next = Transition(ch, States.Error, States.Error, States.Error, States.State15, States.Error); break; default: next = States.Error; break; } return next; } static States Transition(char ch, States whenDigit, States whenSlash, States whenSpace, States whenColon, States whenDot) { States next = States.Error; if (char.IsDigit(ch)) { next = whenDigit; } else if (ch == '/') { next = whenSlash; } else if (ch == ' ') { next = whenSpace; } else if (ch == ':') { next = whenColon; } else if (ch == '.') { next = whenDot; } else { next = States.Error; } return next; } static bool IsError(States state) { return state == States.Error; } } }