2

社内のほとんど ISO に似た形式で次の日付/時刻があるとします。

  • "2011-11-07T11:17"
  • "--T11:17"(午前11時17分、日付なし、時間のみ)
  • "-11-07"(11月7日、年なし、時間なし)

区切り記号は必須であり、データが存在するかどうかを知ることができます。データは次のような構造に設定されます。

struct MyDate
{
    int? Year ;
    int? Month ;
    int? Day ;
    int? Hour ;
    int? Minute ;
}

「最も簡単な」方法は、文字ごとにループし、存在する場合はデータを抽出することです。

しかし、整数などを抽出し、整数以外の最初の文字のインデックスを返す (C の に似た) 何らかの API が必要だというしつこい印象がありますstrtol

strtol文字列を文字ごとに解析する代わりに、C# のような関数、または型指定されたデータを抽出するためのより高レベルの関数はありますか?

4

4 に答える 4

1

私はこのようにそれについて行きます:

編集2

現在含まれています:

  • MyDate構造体の静的メソッドParseとメソッド:)TryParse
  • テストを容易にするためのミラーリングToString()
  • 最小ユニットテストテストケース
  • ボーナスデモンストレーション:文字列からMyDateへの暗黙の変換演算子(したがって、MyDateが必要な場所に文字列を渡すことができます)

繰り返しになりますが、 http://ideone.com/rukw4でライブでご覧ください

using System;
using System.Text;
using System.Text.RegularExpressions;

struct MyDate 
{ 
    public int? Year, Month, Day, Hour, Minute; 

    private static readonly Regex dtRegex = new Regex(
        @"^(?<year>\d{4})?-(?<month>\d\d)?-(?<day>\d\d)?"
    +   @"(?:T(?<hour>\d\d)?:(?<minute>\d\d)?)?$",
        RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);

    public static bool TryParse(string input, out MyDate result)
    {
        Match match = dtRegex.Match(input);
        result = default(MyDate);

        if (match.Success)
        {
            if (match.Groups["year"].Success)
                result.Year = Int32.Parse(match.Groups["year"].Value);
            if (match.Groups["month"].Success)
                result.Month = Int32.Parse(match.Groups["month"].Value);
            if (match.Groups["day"].Success)
                result.Day = Int32.Parse(match.Groups["day"].Value);
            if (match.Groups["hour"].Success)
                result.Hour = Int32.Parse(match.Groups["hour"].Value);
            if (match.Groups["minute"].Success)
                result.Minute = Int32.Parse(match.Groups["minute"].Value);
        }

        return match.Success;
    }

    public static MyDate Parse(string input)
    {
        MyDate result;
        if (!TryParse(input, out result))
            throw new ArgumentException(string.Format("Unable to parse MyDate: '{0}'", input));

        return result;
    }

    public override string ToString()
    {
        return string.Format("{0:0000}-{1:00}-{2:00}T{3:00}:{4:00}", Year, Month, Day, Hour, Minute);
    }

    public static implicit operator MyDate(string input)
    {
        return Parse(input);
    }
}

class Program
{
    static void Main(string[] args)
    {
        foreach (var testcase in new [] { 
                "2011-11-07T11:17",
                "-11-07T11:17",
                "2011--07T11:17",
                "2011-11-T11:17",
                "2011-11-07T:17",
                "2011-11-07T11:",
                // extra:
                "--T11:17", // (11:17 am, no date, only time)
                "-11-07", // (november the 7th, no year, no time)
                // failures:
                "2011/11/07 T 11:17",
                "no match" })
        {
            MyDate parsed;
            if (MyDate.TryParse(testcase, out parsed))
                Console.WriteLine("'{0}' -> Parsed into '{1}'", testcase, parsed);
            else
                Console.WriteLine("'{0}' -> Parse failure", testcase);
        }
    }
}

出力:

'2011-11-07T11:17' -> Parsed into '2011-11-07T11:17'
'-11-07T11:17' -> Parsed into '-11-07T11:17'
'2011--07T11:17' -> Parsed into '2011--07T11:17'
'2011-11-T11:17' -> Parsed into '2011-11-T11:17'
'2011-11-07T:17' -> Parsed into '2011-11-07T:17'
'2011-11-07T11:' -> Parsed into '2011-11-07T11:'
'--T11:17' -> Parsed into '--T11:17'
'-11-07' -> Parsed into '-11-07T:'
'2011/11/07 T 11:17' -> Parse failure
'no match' -> Parse failure
于 2011-11-07T10:46:26.767 に答える
1

パフォーマンスが問題にならない場合は、タスクに正規表現を利用します。

式として使用(\d*)-(\d*)-(\d*)T(\d*):(\d*)し、各キャプチャ グループを構造体の対応するフィールドに解析して、空の文字列をnull値に変換します。

var match = Regex.Match(str, @"(\d*)-(\d*)-(\d*)T(\d*):(\d*)");
var date = new MyDate();

if (match.Groups[1].Value != "") date.Year = int.Parse(match.Groups[1].Value);
if (match.Groups[2].Value != "") date.Month = int.Parse(match.Groups[2].Value);
if (match.Groups[3].Value != "") date.Day = int.Parse(match.Groups[3].Value);
if (match.Groups[4].Value != "") date.Hour = int.Parse(match.Groups[4].Value);
if (match.Groups[5].Value != "") date.Minute = int.Parse(match.Groups[5].Value);

編集: 'T' と ':' の区切り記号は、このコードでは必須です。それ以外の場合は、代わりに @sehe の回答を参照してください。

于 2011-11-07T10:44:03.140 に答える
1

使用できますDateTime.ParseExactここでドキュメントを確認してください

于 2011-11-07T10:32:14.320 に答える
0

DateTime.ParseExactたとえば、使用できる日付形式がわかっている場合...似たようなものが必要なstrtol場合は、Convert.ToInt32.

于 2011-11-07T10:33:28.943 に答える