2

興味深い問題に遭遇しました。先日のコードで。簡単な修正を思いついたのですが、もっと良い方法はないかと考えずにはいられませんでした。

問題は、QueryString を介して送信された文字列値を解析して、最終的に SQL ストアド プロシージャになる型付きオブジェクトにするときに発生します。ほとんどの最終的な比較タイプでは、文字列の比較は問題ありませんが、日付で「より小さい」または「より大きい」などを行うには、最初に文字列を日付に変換する必要があります。

これを行っていたので、値はクエリ文字列から引き出された後、文字列として関数に送信されます。

if (DateTime.TryParse(value, out newTime))
{
    value = newTime.ToStringIsoUtc();
}

return value

誰かが 3 部構成のバージョン番号を送信しようとするまで、これは何年もの間問題なく機能していました。突然 1.3.1 が 2001-03-01 になり、比較が機能しなくなりました。

私の簡単な修正は、潜在的な「日付」に複数のドットがあるかどうかを確認することでした。簡単。しかし、問題は、現在 UTC 日付形式以外を使用しているクライアントはありませんが、ウィキペディアを見て、標準の日付形式として dd.mm.yy のようなものを使用している国がいくつあるかを知って怖くなりました.

日付から型指定されていないバージョン番号を伝えるより良い方法はありますか?

4

2 に答える 2

3

There is no way that you can do this with just the date value alone. What you really need is another value indicating what the format of the DateTime in the querystring is.

Take for example your 1.3.1 format. Who is to say that it's not really able to be interpreted as January 3rd, 2011 (looking at it from left-to-right as opposed to right-to-left).

You have two options:

  • If you want a completely open value, you need a hint indicating how it should be interpreted (which you would use to adjust your call to set the options in the call to DateTime.TryParse), along with the caveat that if the hint is not provided, then the results may be indeterminable when the input is ambiguous

  • Reject anything that isn't in the expected format.

The first is preferable when dealing with user input, as you want to make it as easy as possible for your users and lower the bar to entry.

Note that if the user input is coming from say, a web page that uses HTML 5, you should be aware that the input tag allows for date and datetime input types. Not only does this have the benefit of allowing browsers to provide standardized (at least, across a platform) way of inputting this type of data, but it also provides for standardizing the format that data is transmitted in, meaning your input falls more into #2 than it does in #1.

The second is preferable when When dealing calls made from APIs, as the DateTime instances (or representations of them) can be modified to fit your expectations (since they have a strongly typed representation in memory already before calling your API).

于 2012-11-14T13:12:46.313 に答える
1

Which worked fine for years, until someone tried to submit a three-part version number. Suddenly 1.3.1 became 2001-03-01 and the comparison stopped working.

This would be the reason you should use DateTime ParseExact(string s,string format,IFormatProvider povider )

using System;
using System.Globalization;

public class Example
{
   public static void Main()
   {
      string dateString, format;  
      DateTime result;
      CultureInfo provider = CultureInfo.InvariantCulture;

      // Parse date-only value with invariant culture.
      dateString = "06/15/2008";
      format = "d";
      try {
         result = DateTime.ParseExact(dateString, format, provider);
         Console.WriteLine("{0} converts to {1}.", dateString, result.ToString());
      }
      catch (FormatException) {
         Console.WriteLine("{0} is not in the correct format.", dateString);
      } 

      // Parse date-only value without leading zero in month using "d" format.// Should throw a FormatException because standard short date pattern of  // invariant culture requires two-digit month.
      dateString = "6/15/2008";
      try {
         result = DateTime.ParseExact(dateString, format, provider);
         Console.WriteLine("{0} converts to {1}.", dateString, result.ToString());
      }
      catch (FormatException) {
         Console.WriteLine("{0} is not in the correct format.", dateString);
      }

      // Parse date and time with custom specifier.
      dateString = "Sun 15 Jun 2008 8:30 AM -06:00";
      format = "ddd dd MMM yyyy h:mm tt zzz";
      try {
         result = DateTime.ParseExact(dateString, format, provider);
         Console.WriteLine("{0} converts to {1}.", dateString, result.ToString());
      }
      catch (FormatException) {
         Console.WriteLine("{0} is not in the correct format.", dateString);
      }

      // Parse date and time with offset but without offset's minutes. // Should throw a FormatException because "zzz" specifier requires leading  // zero in hours.
      dateString = "Sun 15 Jun 2008 8:30 AM -06";
      try {
         result = DateTime.ParseExact(dateString, format, provider);
         Console.WriteLine("{0} converts to {1}.", dateString, result.ToString());
      }   
      catch (FormatException) {
         Console.WriteLine("{0} is not in the correct format.", dateString);
      } 

      dateString = "15/06/2008 08:30";
      format = "g";
      provider = new CultureInfo("fr-FR");
      try {
         result = DateTime.ParseExact(dateString, format, provider);
         Console.WriteLine("{0} converts to {1}.", dateString, result.ToString());
      }   
      catch (FormatException) {
         Console.WriteLine("{0} is not in the correct format.", dateString);
      } 
   }
}

Source

于 2012-11-14T13:12:15.477 に答える