আমি কীভাবে নিকটতম এক্স মিনিট পর্যন্ত সময় কাটাতে পারি?


160

সেখানে rounding জন্য একটি সহজ ফাংশন ইউপি একটি DateTimeনিকটতম 15 মিনিট?

যেমন

2011-08-11 16:59 হয়ে 2011-08-11 17:00

2011-08-11 17:00 হিসাবে থাকে 2011-08-11 17:00

2011-08-11 17:01 হয়ে 2011-08-11 17:15

উত্তর:


287
DateTime RoundUp(DateTime dt, TimeSpan d)
{
    return new DateTime((dt.Ticks + d.Ticks - 1) / d.Ticks * d.Ticks, dt.Kind);
}

উদাহরণ:

var dt1 = RoundUp(DateTime.Parse("2011-08-11 16:59"), TimeSpan.FromMinutes(15));
// dt1 == {11/08/2011 17:00:00}

var dt2 = RoundUp(DateTime.Parse("2011-08-11 17:00"), TimeSpan.FromMinutes(15));
// dt2 == {11/08/2011 17:00:00}

var dt3 = RoundUp(DateTime.Parse("2011-08-11 17:01"), TimeSpan.FromMinutes(15));
// dt3 == {11/08/2011 17:15:00}

13
এই সমাধানটি কেবলমাত্র একটি এক্সটেনশন পদ্ধতি হিসাবে আমার ইউটিলিটি লাইব্রেরিতে পরিণত করেছে।
জেলটন

1
চূড়ান্ত সময়গুলি উপরের চরমের কাছাকাছি সময়ে সন্ধান করুন। আপনার গণনা করা টিকগুলি ডেটটাইম.ম্যাক্সভ্যালু.টিক্সের চেয়ে বেশি হলে এটি ব্যতিক্রম ছোঁড়াতে পারে। নিরাপদে থাকুন এবং আপনার গণনা করা মান এবং তারিখটাইম.ম্যাক্সভ্যালু.টিক্সের সর্বনিম্ন নিন।
পল র্যাফ

4
আপনি এই পদ্ধতিতে ডেটটাইম অবজেক্ট থেকে তথ্য হারাচ্ছেন না? ধরনের এবং সময় অঞ্চল মত, যদি সেট আছে?
এভরেন কুজুকুগলু

11
@ ব্যবহারকারী 14 .. (+ ডি। টিক্স - 1) নিশ্চিত করে যে এটি প্রয়োজনে এটির চারপাশে চলেছে। / এবং * গোলাকার হয়। 12 এর পরের 5 এর রাউন্ড উদাহরণ: (12 + 5 - 1) = 16,
16/5

12
@ ডিটিবি একটি ছোট সংযোজন, অন্যথায় এটি সম্ভবত সামান্য বাগড: আপনার DateTime RoundUp(DateTime dt, TimeSpan d) { return new DateTime(((dt.Ticks + d.Ticks - 1) / d.Ticks) * d.Ticks, dt.Kind); }
ডেটটাইম

107

যে একটি সমাধান সঙ্গে যুক্ত নয় নিয়ে এসেছেন গুন এবং বিভাজক long নম্বর।

public static DateTime RoundUp(this DateTime dt, TimeSpan d)
{
    var modTicks = dt.Ticks % d.Ticks;
    var delta = modTicks != 0 ? d.Ticks - modTicks : 0;
    return new DateTime(dt.Ticks + delta, dt.Kind);
}

public static DateTime RoundDown(this DateTime dt, TimeSpan d)
{
    var delta = dt.Ticks % d.Ticks;
    return new DateTime(dt.Ticks - delta, dt.Kind);
}

public static DateTime RoundToNearest(this DateTime dt, TimeSpan d)
{
    var delta = dt.Ticks % d.Ticks;
    bool roundUp = delta > d.Ticks / 2;
    var offset = roundUp ? d.Ticks : 0;

    return new DateTime(dt.Ticks + offset - delta, dt.Kind);
}

ব্যবহার:

var date = new DateTime(2010, 02, 05, 10, 35, 25, 450); // 2010/02/05 10:35:25
var roundedUp = date.RoundUp(TimeSpan.FromMinutes(15)); // 2010/02/05 10:45:00
var roundedDown = date.RoundDown(TimeSpan.FromMinutes(15)); // 2010/02/05 10:30:00
var roundedToNearest = date.RoundToNearest(TimeSpan.FromMinutes(15)); // 2010/02/05 10:30:00

8
আমি নিশ্চিতভাবে ভেবেছিলাম যে এটি গুণ এবং বিভাগ ব্যবহারের চেয়ে দ্রুত হবে তবে আমার পরীক্ষায় দেখা যায় যে এটি তা নয়। এটি প্রায় 10000000 পুনরাবৃত্তির পরে, মডিউলাস পদ্ধতিটি আমার মেশিনে 610 ডলার নিয়েছিল, যখন বহু / ডিভ পদ্ধতিতে ms 500ms নেওয়া হয়েছিল। আমার ধারণা এফপিইউগুলি পুরনোদের উদ্বেগকে অ-ইস্যু করে তোলে। এখানে আমার পরীক্ষার কোডটি রয়েছে: pastie.org/8610460
স্নিগ্ধতা

1
এক্সটেনশনের দুর্দান্ত ব্যবহার। ধন্যবাদ!
ট্র্যাভিসবিহীন

1
ধন্যবাদ আমি উত্তর আপডেট করেছি। আমি পার্থক্যটি দেখানোর জন্য আপনার কোডটি দিয়ে এই আদর্শটি তৈরি করেছি: ideone.com/EVKFp5
redent84

1
এই বেশ বুড়ো হয়ে যাচ্ছেন, কিন্তু শেষ হয় %d.TicksRoundUpপ্রয়োজনীয়? d.Ticks - (dt.Ticks % d.Ticks))অগত্যা কম হবে d.Ticks, সুতরাং উত্তর একই সঠিক হওয়া উচিত?
নাইট ডায়মন্ড

1
কেবল দেখানো, মডুলাস হল সিপিইউতে একটি বিভাগ অপারেশন প্রয়োজন। তবে আমি সম্মত হই যে পূর্ণসংখ্যা বিভাগগুলির রডিং ডাউন সম্পত্তি ব্যবহার করা আরও মার্জিত।
অ্যালেক্স

19

আপনার যদি নিকটতম সময়ের ব্যবধানে (আপ না করা) গোল করতে হয় তবে আমি নিম্নলিখিতটি ব্যবহার করার পরামর্শ দিই

    static DateTime RoundToNearestInterval(DateTime dt, TimeSpan d)
    {
        int f=0;
        double m = (double)(dt.Ticks % d.Ticks) / d.Ticks;
        if (m >= 0.5)
            f=1;            
        return new DateTime(((dt.Ticks/ d.Ticks)+f) * d.Ticks);
    }

এই উত্তর সঠিকভাবে গোল হয় না। (হাস্যকর নিচে- ভোট কারণ প্রশ্ন আপ rounding abt ছিল): user1978424 কেবল নীচের নিকটতম ব্যবধান বৃত্তাকার সঠিকভাবে কিভাবে যে শো পোষ্ট করেছেন
stitty

8
void Main()
{
    var date1 = new DateTime(2011, 8, 11, 16, 59, 00);
    date1.Round15().Dump();

    var date2 = new DateTime(2011, 8, 11, 17, 00, 02);
    date2.Round15().Dump();

    var date3 = new DateTime(2011, 8, 11, 17, 01, 23);
    date3.Round15().Dump();

    var date4 = new DateTime(2011, 8, 11, 17, 00, 00);
    date4.Round15().Dump();
}

public static class Extentions
{
    public static DateTime Round15(this DateTime value)
    {   
        var ticksIn15Mins = TimeSpan.FromMinutes(15).Ticks;

        return (value.Ticks % ticksIn15Mins == 0) ? value : new DateTime((value.Ticks / ticksIn15Mins + 1) * ticksIn15Mins);
    }
}

ফলাফল:

8/11/2011 5:00:00 PM
8/11/2011 5:15:00 PM
8/11/2011 5:15:00 PM
8/11/2011 5:00:00 PM

3
2011-08-11 17:00:01কেটে যায়2011-08-11 17:00:00
জেলটন

1
@ জেলটন: +1 দেখানোর জন্য ধন্যবাদ Thanks আমি আমার কোড পরিবর্তন করে যে এটি উপযুক্ত।
ভ্লাদ বেজডেন

সহজ যাচাইকরণের জন্য আপনার কোড লিনকপ্যাড ফর্ম্যাটটি প্রদান করা একটি দুর্দান্ত সময় বাঁচানো। ব্যবহার করা খুব সহজ।
অ্যাডাম গারনার

6

যেহেতু আমি চাকাটিকে পুনরায় উদ্ভাবন করা ঘৃণা করি, তাই সম্ভবত একটি নির্দিষ্ট সময়বৃত্তির (টাইমস্প্যান) ডেটটাইম মানকে গোল করার জন্য আমি সম্ভবত এই অ্যালগরিদমটি অনুসরণ করব:

  • DateTimeপুরো এবং ভগ্নাংশের TimeSpanইউনিটের প্রতিনিধিত্ব করে দশমিক ভাসমান-বিন্দুতে গোল করতে মানটিকে রূপান্তর করুন ।
  • একটি পূর্ণসংখ্যার সাথে এটি ব্যবহার করে গোল করুন Math.Round()
  • TimeSpanইউনিটে টিক্সের সংখ্যার সাহায্যে বৃত্তাকার পূর্ণসংখ্যাটিকে গুণ করে টিক্স-এ স্কেল করুন ।
  • DateTimeগোল টিক্সের গোল সংখ্যা থেকে একটি নতুন মান ইনস্ট্যান্ট করুন এবং কলারের কাছে এটি ফিরিয়ে দিন।

কোডটি এখানে:

public static class DateTimeExtensions
{

    public static DateTime Round( this DateTime value , TimeSpan unit )
    {
        return Round( value , unit , default(MidpointRounding) ) ;
    }

    public static DateTime Round( this DateTime value , TimeSpan unit , MidpointRounding style )
    {
        if ( unit <= TimeSpan.Zero ) throw new ArgumentOutOfRangeException("unit" , "value must be positive") ;

        Decimal  units        = (decimal) value.Ticks / (decimal) unit.Ticks ;
        Decimal  roundedUnits = Math.Round( units , style ) ;
        long     roundedTicks = (long) roundedUnits * unit.Ticks ;
        DateTime instance     = new DateTime( roundedTicks ) ;

        return instance ;
    }

}

এটি নিকটতম গোলাকার জন্য দুর্দান্ত কোড DateTime, তবে আমি একাধিক পর্যন্ত গোল করার ক্ষমতাও চাই unit । মধ্যে পাসিং MidpointRounding.AwayFromZeroকরতে Roundআকাঙ্ক্ষিত ফল নেই। কোন MidpointRoundingযুক্তি স্বীকার করে আপনার মনে কি অন্য কিছু আছে ?
শুভনোমাদ

2

আমার সংস্করণ

DateTime newDateTimeObject = oldDateTimeObject.AddMinutes(15 - oldDateTimeObject.Minute % 15);

একটি পদ্ধতি হিসাবে এটি এটি লক হবে

public static DateTime GetNextQuarterHour(DateTime oldDateTimeObject)
{
    return oldDateTimeObject.AddMinutes(15 - oldDateTimeObject.Minute % 15);
}

এবং এটি বলা হয়

DateTime thisIsNow = DateTime.Now;
DateTime nextQuarterHour = GetNextQuarterHour(thisIsNow);

এটি সেকেন্ডের জন্য অ্যাকাউন্ট করে না
অ্যালেক্স নরক্লিফ

1

মার্জিত?

dt.AddSeconds(900 - (x.Minute * 60 + x.Second) % 900)

1
আরও সঠিক সংস্করণটি হ'ল: এক্স.এডসেকেন্ডস (900 - (এক্স। অ্যাডসেকেন্ডস -1) .মিনিট * 60 + এক্স.এডসেকেন্ডস (-1)। সেকেন্ড)% 900)। অ্যাডসেকেন্ডস (-1), যা যত্ন নেয় "স্থিতি" শর্ত
ওলাফ

1

সাবধানতা: উপরের সূত্রটি ভুল, অর্থাৎ নিম্নলিখিত:

DateTime RoundUp(DateTime dt, TimeSpan d)
{
    return new DateTime(((dt.Ticks + d.Ticks - 1) / d.Ticks) * d.Ticks);
}

এইভাবে আবার লিখতে হবে:

DateTime RoundUp(DateTime dt, TimeSpan d)
{
    return new DateTime(((dt.Ticks + d.Ticks/2) / d.Ticks) * d.Ticks);
}

1
আমি একমত নই যেহেতু পূর্ণসংখ্যা বিভাগটি / d.Ticksনিকটতম 15-মিনিটের ব্যবধানে চলে আসে (আসুন আমরা এইগুলিকে "ব্লকগুলি বলি), কেবলমাত্র একটি অর্ধেক ব্লক যোগ করা গোলাকার গ্যারান্টি দেয় না। আপনার যখন 4.25 ব্লক রয়েছে তখন বিবেচনা করুন। আপনি যদি 0.5 টি ব্লক যুক্ত করেন, তবে পরীক্ষা করুন যে আপনার কাছে কতগুলি পূর্ণসংখ্যক ব্লক রয়েছে, আপনার এখনও কেবল 4 টি রয়েছে block একটি ব্লক সম্পূর্ণ ব্লকের চেয়ে কম যুক্ত করা সঠিক ক্রিয়া। এটি নিশ্চিত করে যে আপনি সর্বদা পরবর্তী ব্লকের পরিসরে যান (গোল করার আগে), তবে আপনাকে সঠিক ব্লকের মধ্যে যাওয়ার থেকে বাধা দেয়। (IE, আপনি যদি 4.0 ব্লকে একটি সম্পূর্ণ ব্লক যুক্ত করেন তবে 5.0 এর পরিমাণ 5 হবে, আপনি যখন চান 4. 4.99 হবে 4.)
ব্রেন্ডন মুর

1

আরও ভার্জোজ সমাধান, যা মডিউলো ব্যবহার করে এবং অপ্রয়োজনীয় গণনা এড়ায়।

public static class DateTimeExtensions
{
    public static DateTime RoundUp(this DateTime dt, TimeSpan ts)
    {
        return Round(dt, ts, true);
    }

    public static DateTime RoundDown(this DateTime dt, TimeSpan ts)
    {
        return Round(dt, ts, false);
    }

    private static DateTime Round(DateTime dt, TimeSpan ts, bool up)
    {
        var remainder = dt.Ticks % ts.Ticks;
        if (remainder == 0)
        {
            return dt;
        }

        long delta;
        if (up)
        {
            delta = ts.Ticks - remainder;
        }
        else
        {
            delta = -remainder;
        }

        return dt.AddTicks(delta);
    }
}

0

এটি নিকটতম 1 মিনিট পর্যন্ত গোল করার সহজ সমাধান। এটি ডেটটাইমের টাইমজোন এবং ধরনের তথ্য সংরক্ষণ করে। এটি আপনার নিজের প্রয়োজন অনুসারে আরও সংশোধন করা যেতে পারে (যদি আপনার নিকটতম 5 মিনিট ইত্যাদি প্রয়োজন হয়)।

DateTime dbNowExact = DateTime.Now;
DateTime dbNowRound1 = (dbNowExact.Millisecond == 0 ? dbNowExact : dbNowExact.AddMilliseconds(1000 - dbNowExact.Millisecond));
DateTime dbNowRound2 = (dbNowRound1.Second == 0 ? dbNowRound1 : dbNowRound1.AddSeconds(60 - dbNowRound1.Second));
DateTime dbNow = dbNowRound2;

0

আপনি এই পদ্ধতিটি ব্যবহার করতে পারেন, এটি তারিখের সময় অবজেক্টে পূর্বে উল্লিখিত বিশ্বায়ন এবং তারিখের সময় ধরণের কোনওটি বজায় রাখে তা নিশ্চিত করতে নির্দিষ্ট তারিখটি ব্যবহার করে।

const long LNG_OneMinuteInTicks = 600000000;
/// <summary>
/// Round the datetime to the nearest minute
/// </summary>
/// <param name = "dateTime"></param>
/// <param name = "numberMinutes">The number minute use to round the time to</param>
/// <returns></returns>        
public static DateTime Round(DateTime dateTime, int numberMinutes = 1)
{
    long roundedMinutesInTicks = LNG_OneMinuteInTicks * numberMinutes;
    long remainderTicks = dateTime.Ticks % roundedMinutesInTicks;
    if (remainderTicks < roundedMinutesInTicks / 2)
    {
        // round down
        return dateTime.AddTicks(-remainderTicks);
    }

    // round up
    return dateTime.AddTicks(roundedMinutesInTicks - remainderTicks);
}

। নেট ফিডল টেস্ট

আপনি যদি সময় কাটাতে টাইমস্প্যান ব্যবহার করতে চান তবে আপনি এটি ব্যবহার করতে পারেন।

/// <summary>
/// Round the datetime
/// </summary>
/// <example>Round(dt, TimeSpan.FromMinutes(5)); => round the time to the nearest 5 minutes.</example>
/// <param name = "dateTime"></param>
/// <param name = "roundBy">The time use to round the time to</param>
/// <returns></returns>        
public static DateTime Round(DateTime dateTime, TimeSpan roundBy)
{            
    long remainderTicks = dateTime.Ticks % roundBy.Ticks;
    if (remainderTicks < roundBy.Ticks / 2)
    {
        // round down
        return dateTime.AddTicks(-remainderTicks);
    }

    // round up
    return dateTime.AddTicks(roundBy.Ticks - remainderTicks);
}

টাইমস্প্যান ফিডল


আপনি যদি নিকটতম 7th তম মিনিটে গোল করতে চান তবে কি হবে var d = new DateTime(2019, 04, 15, 9, 40, 0, 0);// 9:42 হওয়া উচিত তবে এই পদ্ধতির কোনওটিই এর মতো কাজ করে না?
ডটনেটশাদো

সম্পাদনা দেখে মনে হচ্ছে @ স্যলফ্লিম্যান উত্তর সঠিক ফলাফল
আনবে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.