31

API エンドポイントを作成しました。呼び出し元はPOST、関連するパラメーターを渡すメソッドで API を呼び出すことができます。パラメータには、datetime形式のパラメータが 1 つあります。

問題は、この API を呼び出すときに、呼び出し元がdatetime3 つの異なる形式で渡す可能性があることです。

  1. long int- 例: 1374755180
  2. 米国形式 - 例: "7/25/2013 6:37:31 PM" (as string)
  3. タイムスタンプ形式 - 例: "2013-07-25 14:26:00" (as string)

datetime値を解析して、DateTimeまたはstringタイムスタンプ形式に変換する必要があります。

DateTime.TryParse()DateTime.Parse()Convert.ToDateTime()およびを使用してみConvert.ToDouble()ましたが、確実に機能するものはありません。

必要な出力はen-GBフォーマットされている必要があります。

編集:

文字列を解析できなかったと言うために、if-else if-elseブロックをTryParse3 回使用することを考えていました。elseこれが最善の解決策ですか?または、これよりも優れたソリューションはありますか?

助けてください!

4

7 に答える 7

32

タイムゾーンを要求することを検討する必要があります。1 は必要ありませんが、2 と 3 は必要です。

public DateTime ParseRequestDate()
{
    // https://stackoverflow.com/questions/2883576/how-do-you-convert-epoch-time-in-c

    CultureInfo enUS = new CultureInfo("en-US");

    var dt = "1374755180";
    //var dt = "7/25/2013 6:37:31 PM";
    //var dt = "2013-07-25 14:26:00";

    DateTime dateValue;
    long dtLong;

    // Scenario #1
    if (long.TryParse(dt, out dtLong))
        return dtLong.FromUnixTime();

    // Scenario #2
    if (DateTime.TryParseExact(dt, "MM/dd/yyyy hh:mm:ss tt", enUS, DateTimeStyles.None, out dateValue))
        return dateValue;

    // Scenario #3
    if (DateTime.TryParseExact(dt, "yyyy-MM-dd hh:mm:ss", enUS, DateTimeStyles.None, out dateValue))
        return dateValue;

    throw new SomeException("Don't know how to parse...");
}

EDIT Matt Johnson が指摘しているように、DateTime.TryParseExact はフォーマット文字列の配列を受け入れます。2と3は凝縮できます。

public DateTime ParseRequestDate()
{
    // https://stackoverflow.com/questions/2883576/how-do-you-convert-epoch-time-in-c

    CultureInfo enUS = new CultureInfo("en-US");

    var dt = "1374755180";
    //var dt = "7/25/2013 6:37:31 PM";
    //var dt = "2013-07-25 14:26:00";

    DateTime dateValue;
    long dtLong;

    // Scenario #1
    if (long.TryParse(dt, out dtLong))
        return dtLong.FromUnixTime();

    // Scenario #2 & #3
    var formatStrings = new string[] { "MM/dd/yyyy hh:mm:ss tt", "yyyy-MM-dd hh:mm:ss" };
    if (DateTime.TryParseExact(dt, formatStrings, enUS, DateTimeStyles.None, out dateValue))
        return dateValue;

    throw new SomeException("Don't know how to parse...");
}

別の質問から借りたエポック変換。 (延長方法)

public static class MyExtensions
{
    public static DateTime FromUnixTime(this long unixTime)
    {
        var epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
        return epoch.AddSeconds(unixTime);
    }
}
于 2013-07-25T13:51:03.113 に答える
27

あなたが探しているDateTime.ParseExact( MSDN の記事)

次のような状況で使用します。

string[] formats= { "MM/dd/yyyy hh:mm:ss tt", "yyyy-MM-dd hh:mm:ss" }
var dateTime = DateTime.ParseExact("07/25/2013 6:37:31 PM", formats, new CultureInfo("en-GB"), DateTimeStyles.None);

DateTimeこれにより、必要な数の形式をに追加でき、メソッドは...ステートメントarrayなしで変換を行います。ifelse

整数がUnix エポック以降の秒数である場合、エポック (1970 年 1 月 1 日) の DateTime に秒数を追加します (.Net には、このためのすぐに使用できるメソッドはありませんが、ロジックは秒です。 '時代'):

new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(seconds);

この質問から。

于 2013-07-25T13:49:56.857 に答える
2

私のコードがさまざまなカルチャ形式のさまざまな環境で実行されるプロジェクトで、同じ問題に直面していました。

Google がこの隠れた逸品を見せてくれました。ヘルパー関数は、カルチャ形式に関係なく適切に日時を自動解析するために不可欠です

使用例:

string str = @"The last round was June 10, 2005; this time the unbroken record was held.";
DateTimeRoutines.ParsedDateTime pdt;
if (DateTimeRoutines.TryParseDate(str, DateTimeRoutines.DateTimeFormat.USA_DATE, out pdt))
    Console.WriteLine("Date was found: " + pdt.DateTime.ToString());

著者によると、コードはさまざまなケースを解析できます。

@"Member since:      10-Feb-2008"
@"Last Update: 18:16 11 Feb '08 "
@"date    Tue, Feb 10, 2008 at 11:06 AM"
@"see at 12/31/2007 14:16:32"
@"sack finish 14:16:32 November 15 2008, 1-144 app"
@"Genesis Message - Wed 04 Feb 08 - 19:40"
@"The day 07/31/07 14:16:32 is "
@"Shipping is on us until December 24, 2008 within the U.S." 
@" 2008 within the U.S. at 14:16:32"
@"5th November, 1994, 8:15:30 pm"
@"7 boxes January 31 , 14:16:32."
@"the blue sky of Sept  30th  2008 14:16:32"
@" e.g. 1997-07-16T19:20:30+01:00"
@"Apr 1st, 2008 14:16:32 tufa 6767"
@"wait for 07/31/07 14:16:32"
@"later 12.31.08 and before 1.01.09"
@"Expires: Sept  30th  2008 14:16:32"
@"Offer expires Apr 1st, 2007, 14:16:32"
@"Expires  14:16:32 January 31."
@"Expires  14:16:32 January 31-st."
@"Expires 23rd January 2010."
@"Expires January 22nd, 2010."
@"Expires DEC 22, 2010."
于 2015-04-01T14:39:55.750 に答える
2

この問題に対処する 1 つの方法は、さまざまな形式を「理解」し、それに応じて解析するファクトリ メソッドを設定することです。

ifこの問題に対処するために--thenのチェーンを作成できますelseが、「テーブル駆動型」の実装を作成することもできます。必要なのは、文字列を受け取り、次の 2 つのことを伝えるデリゲートの配列です。

  • このデリゲートが着信文字列を解析できるかどうか、および
  • はいの場合、その解析の結果は次のように表されますDateTime

実装例を次に示します。

private static readonly DateParsers = new Func<string,Tuple<DateTime,bool>>[] {
    (s) => {
        long res;
        if (long.TryParse(s, out res)) {
            // The format was correct - make a DateTime,
            // and return true to indicate a successful parse
            return Tuple.Create(new DateTime(res), true);
        } else {
            // It does not matter what you put in the Item1
            // when Item2 of the tuple is set to false
            return Tuple.Create(DateTime.MinValue, false);
        }
    }
    ...
    // Add similar delegates for other formats here
};

これで、ファクトリ メソッドを次のように実装できます。

private static bool TryParseMultiformat(string s, out DateTime res) {
    // Check all parsers in turn, looking for one returning success
    foreach (var p in DateParsers) {
        var tmp = p(s);
        if (tmp.Item2) {
            res = tmp.Item1;
            return true;
        }
    }
    res = DateTime.MinValue;
    return false;
}
于 2013-07-25T13:47:40.670 に答える
1

可能な形式が修正されている場合は、TryParseExactを使用できます

考えられる解決策は、 TryParseを使用することです。適切な日付を取得できない場合は、既知の形式にフォールバックしてTryPraseExactを使用します

于 2013-07-25T13:33:50.403 に答える
0

を使用する場合TryParseExact、GOD と Microsoft の開発者だけが、あきらめる前に解析を試みる可能性のある日時形式を知っています。おそらく、より良い解決策は、迅速な正規表現を使用してから適切なパーサーを使用することです。可能な限り単純な正規表現を作成しようとしましたが、これを少し調整する必要があるかもしれません

    private  static readonly Regex R1
        = new Regex(@"^\d+$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
    private static readonly Regex R2
        = new Regex(@"M$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
    private static readonly Regex R3
        = new Regex(@"^\d{4}-", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);

    private static void Main(string[] args)
    {
        string[] stringDates = new[]
            {
                "1374755180",
                "2013-07-25 14:26:00",
                "7/25/2013 6:37:31 PM"
            };


        foreach (var s in stringDates)
        {
            DateTime date = default(DateTime);
            if (R1.IsMatch(s))
                date = new DateTime(long.Parse(s));
            else if (R2.IsMatch(s))
                date = DateTime.Parse(s);
            else if (R3.IsMatch(s))
                date = DateTime.Parse(s);

            if (date != default(DateTime))
                Console.WriteLine("{0}", date);
        }

        Console.WriteLine("Press ENTER to continue...");
        Console.ReadLine();
    }
于 2013-07-25T14:33:02.777 に答える