2012-01-18 14 views
2

私は、Google CalendarとOutlookがすべての時刻エントリが30分​​離れている時間選択を処理する方法をエミュレートしようとしています。私はほとんどすべてのことを1つのことを除いて機能テストで処理しています。私の問題は、現在の日付を常に最長30分に丸める方法を理解できないことです。これは、と午前8時56分午前を言う(私はこれは午前12:30を返すことを期待する)午前12時00分を除くほとんどの場合のために働くDateTimeを30分に丸めるときに何分もなく時間を処理する

protected DateTime GetStartTime() 
{ 
    var spanTicks = TimeSpan.FromMinutes(30).Ticks; 
    var ticks = (Time.Now.Ticks + spanTicks - 1)/spanTicks; 

    return new DateTime(ticks * spanTicks); 
} 

(:

私は、次のコードを使用しています私はそれが午前9時に戻ると期待しています)。

どうすればこの問題を解決できますか?

+2

なぜ午前12:00には午前12:30になる必要がありますか? 12:00 amは30分の倍数です。そして、あなたのコードによって、午前8時56分が丸められます。あなたのコードが正しいと思います。参照:[C#を最長X分に丸める](http://stackoverflow.com/questions/7029353/c-sharp-round-up-time-to-nearest-x-minutes/7029464#7029464) – dtb

+0

12 :私は扱っているビジネスルールなので、00amは12:30になるはずです。 – Nosila

答えて

1

は、.NETは、あなたのためのすべての特別な場合の世話をしてみましょう:

var now = DateTime.Now; 
DateTime result = now.AddMinutes(now.Minute >= 30 ? (60-now.Minute) : (30-now.Minute)); 
result = result.AddSeconds(-1* result.Second); // To reset seconds to 0 
result = result.AddMilliseconds(-1* result.Millisecond); // To reset milliseconds to 0 
2

なぜティックが気になるのですか?あなたはこのように、正確に:30または:00までの時間を強制することができます。

protected DateTime GetStartTime() { 
    var now = DateTime.Now; 
    int addHours; 
    int minute; 
    if (now.Minute >= 30) { 
     addHour = 1; 
     minute = 0; 
    } else { 
     addHour = 0; 
     minute = 30; 
    } 
    return new DateTime(now.Year, now.Month, now.Day, hour, minute, 0).AddHours(addHours); 
} 
+0

15時45分は16時に、15時半は四捨五入しないでください。 – dtb

+0

これは正しくないようです。 – Groo

+1

@Groo 1時間ごとにバグを修正しました。 – dasblinkenlight

2

EDIT:ORIGINALバージョンは動作しませんでした!古いMonoの厄介な実装から来た!

新バージョン:

protected DateTime GetStartTime() 
{ 
    DateTime dt=DateTime.Now; 
    if (dt.Minute<30) 
    { 
     dt=dt.AddMinutes(30-dt.Minute); 
    } 
    else 
    { 
     dt=dt.AddMinutes(60-dt.Minute); 
    } 

    //dt now has the upcoming half-hour border 

    //... 

} 
+0

DateTimeの値は不変です。 'dt.Minute'に割り当てることはできません。 'dt.AddMinutes'は' dt'を変更しませんが、新しい値を返します。 – dtb

+0

@dtb:私はUbuntuで作業しているMonoバグを見つけたばかりで、dt.Minute = 30;はうまくいきました。より新しいMonoで試してみます。 –

+0

@dtb:現在のモノは正しいですが、DateTimeは不変なので、dt.Minutes = 30は機能しません。 –

1

あなたは次のようなものを試してみましたか?私は正常に

private static readonly long _ticksIn30Mins = TimeSpan.FromMinutes(30).Ticks; 

protected DateTime GetRoundedTime(DateTime inputTime) 
{  
    long currentTicks = inputTime.Ticks; 
    return new DateTime(currentTicks.RoundUp(_ticksIn30Mins)); 
} 

public static class ExtensionMethods 
{  
    public static long RoundUp(this long i, long toTicks)  
    {   
     return (long)(Math.Round(i/(double)toTicks, 
        MidpointRounding.AwayFromZero)) * toTicks; 
    } 
} 

これはRoundOff method from this previous question取る...次の時間、分、日などに切り上げると同様の方法を使用しています。 MidpointRoundingMode.AwayFromZeroを使用して常に丸めるように変更するだけです。最後に、あなたの丸め前と値を丸めた後は同じであり、その場合、(例えば30分)ダニの切り上げ量を増加さかどうかを確認後、午前12:30になってきて午前12時00分の特定の場合に対処する

この原理を実証テストコンソールアプリケーションのために
var currentTime = DateTime.Now; 
var rounded = GetRoundedTime(currentTime); 
if (rounded == currentTime) 
{ 
    rounded = new DateTime(rounded.Ticks + _ticksIn30Mins); 
} 

、下記を参照してください。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     private static readonly long _ticksIn30Mins = TimeSpan.FromMinutes(30).Ticks; 

     static void Main(string[] args) 
     { 
      WriteDateString(new DateTime(2012, 01, 18, 09, 45, 11, 152)); 
      WriteDateString(new DateTime(2012, 01, 18, 12, 15, 11, 999)); 
      WriteDateString(new DateTime(2012, 01, 18, 12, 00, 00, 000)); 

      Console.ReadLine(); 
     } 

     private static void WriteDateString(DateTime dateTime) 
     { 
      Console.WriteLine("Before: {0}, After: {1}", dateTime, GetRoundedTime(dateTime)); 
     } 

     private static DateTime GetRoundedTime(DateTime inputTime) 
     { 
      long currentTicks = inputTime.Ticks; 
      var rounded = new DateTime(currentTicks.RoundUp(_ticksIn30Mins)); 
      if (rounded == inputTime) 
      { 
       rounded = new DateTime(rounded.Ticks + _ticksIn30Mins); 
      } 
      return rounded; 
     } 
    } 

    public static class ExtensionMethods 
    { 
     public static long RoundUp(this long i, long toTicks) 
     { 
      return (long)(Math.Round(i/(double)toTicks, MidpointRounding.AwayFromZero)) * toTicks; 
     } 
    } 
} 

出力:

Console output from date roundup example

敬具、

関連する問題