2012-04-03 15 views
7

क्या डेटटाइम इंस्टेंस बनाने और मिनटों \ सेकंड \ मिली से 0 मिनट सेट करने का कोई तेज़ तरीका है? इस समय मैं निम्नलिखित कोड का उपयोग कर रहा:जोडा-टाइम डेटटाइम के साथ प्रदर्शन समस्या *()

private DateTime createDateTime(java.util.Date date, org.joda.time.Chronology chronology) { 
    DateTime dateTime = new DateTime(date, chronology); 
    dateTime = dateTime.withMinuteOfHour(0); 
    dateTime = dateTime.withSecondOfMinute(0); 
    dateTime = dateTime.withMillisOfSecond(0); 
    return dateTime; 
} 

लेकिन जब यह 200.000 के बारे में बार का आह्वान, dateTime.with *** (0); बहुत समय लगता है शायद अधिक सही समाधान है?

उत्तर

8

शायद यह पसंद है?

// Truncate minutes/seconds/milliseconds from the date's timestamp 
long truncatedTimestamp = date.getTime() - date.getTime() % 3600000; 
DateTime dateTime = new DateTime(truncatedTimestamp, chronology);  

यह तेज़ क्यों है?

  • मेरे समाधान DateTime निर्माता में तेजी से पूर्णांक गणित (नगण्य) और 1 यूनिक्स टाइमस्टैम्प सामान्य (महंगा) का उपयोग करता
  • आपका समाधान का उपयोग करता 1 यूनिक्स टाइमस्टैम्प सामान्य DateTime निर्माता में (महंगा) और 3 अधिक normalisations (महंगा), हर बार जब आप करने के लिए 0
  • अन्य समाधान कुछ तारीख हिस्सा सेट कोड के कम लाइनों की आवश्यकता हो सकती है, लेकिन जब आप JodaTime स्रोतों को देखो, वे भी अधिक से अधिक 3 normalisations (महंगा आवश्यकता होती है)

इसलिए, आप शायद मॉड्यूलो को हरा नहीं सकते हैं। जैसा कि अन्य ने इंगित किया है, इससे बहुत ही दूरस्थ कोने-मामलों में गलत परिणाम हो सकते हैं, जहां घंटे 60 सेकंड (जैसे लीप सेकेंड के कारण) की गणना नहीं करते हैं, हालांकि मैं यह देखने में असफल रहता हूं कि यूनिक्स टाइमस्टैम्प को हमेशा कैसे छोटा किया जा सकता है शून्य, कैलेंडर घंटे की शुरुआत प्राप्त करने के लिए (उदाहरण स्वागत है)।

+0

एक मिनट में निश्चित संख्या में सेकंड नहीं हैं, इसलिए कुछ मौकों पर यह गलत होगा। – Dunes

+0

अंकगणित है, विशेष रूप से मॉड्यूलो गणना 3 सेट विधि से तेज है? इसके अलावा, date.getTime(), आपने दो बार ऐसा किया, तो 2 गेटर्स और गणना, क्या यह 3 सेटर्स से वास्तव में तेज़ है? और चूंकि वह 0 से घंटों तक बस रहा है, यह भी नहीं होना चाहिए, 3600000 * 24 – Churk

+0

@Churk: इन मामूली चीज़ों के बारे में चिंता न करें। 'साथ' विधि में महंगा क्या है पूर्ण दिनांक-समय अंकगणित है। नोट, ओपी घंटे 0 घंटे –

5

बस नीचे दिए गए कोड की कोशिश की - यह विधि 1 (तुम्हारा) की तरह लग रहा है बनाम विधि 2 (मेरा) 390ms, मेरे पीसी पर 320ms के बारे में लेता है , बनाम विधि 3 (लुकास) 15ms, बनाम विधि 4 (MutableDateTime) 310ms ... अब मॉड्यूलो (?) गलत परिणामों का कारण बन सकता है।

सापेक्ष:

public class Test { 

    private static int NUM_RUN; 

    public static void main(String[] args) { 

     Date date = new Date(); 
     List<Runnable> list = new ArrayList<>(); 

     list.add(method3Withs(date)); 
     list.add(method1With(date)); 
     list.add(methodModulo(date)); 
     list.add(methodMutable(date)); 

     NUM_RUN = 100_000; 
     for (Runnable r : list) { 
      long start = System.nanoTime(); 
      r.run(); 
      long end = System.nanoTime(); 
      System.out.println((end - start)/1000000); 
     } 

     NUM_RUN = 10_000_000; 
     for (Runnable r : list) { 
      long start = System.nanoTime(); 
      r.run(); 
      long end = System.nanoTime(); 
      System.out.println((end - start)/1000000); 
     } 
    } 

    private static Runnable method3Withs(final Date date) { 
     return new Runnable() { 

      @Override 
      public void run() { 
       DateTime d2 = null; 
       for (int i = 0; i < NUM_RUN; i++) { 
        d2 = new DateTime(date); 
        d2 = d2.withMinuteOfHour(0); 
        d2 = d2.withSecondOfMinute(0); 
        d2 = d2.withMillisOfSecond(0); 
       } 
       System.out.println(d2); 
      } 
     }; 
    } 

    private static Runnable method1With(final Date date) { 
     return new Runnable() { 

      @Override 
      public void run() { 
       DateTime d2 = null; 
       for (int i = 0; i < NUM_RUN; i++) { 
        d2 = new DateTime(date); 
        d2 = d2.withTime(d2.getHourOfDay(), 0, 0, 0); 
       } 
       System.out.println(d2); 
      } 
     }; 
    } 
    private static Runnable methodModulo(final Date date) { 
     return new Runnable() { 

      @Override 
      public void run() { 
       DateTime d2 = null; 
       for (int i = 0; i < NUM_RUN; i++) { 
        long truncatedTimestamp = date.getTime() - date.getTime() % 3600000; 
        d2 = new DateTime(truncatedTimestamp); 
       } 
       System.out.println(d2); 
      } 
     }; 
    } 

    private static Runnable methodMutable(final Date date) { 
     return new Runnable() { 

      @Override 
      public void run() { 
       MutableDateTime m = null; 
       for (int i = 0; i < NUM_RUN; i++) { 
        m = new MutableDateTime(date); 
        m.setMinuteOfHour(0); 
        m.setSecondOfMinute(0); 
        m.setMillisOfSecond(0); 
       } 
       System.out.println(m); 
      } 
     }; 
    } 
} 

संपादित
मैं इसे 10 लाख रन 100,000 के एक अभ्यास दौर के बाद किए गए विधि एक बड़े से जीतता है मार्जिन, तो ऐसा लगता है कि यह ज्यादातर स्थितियों में बेहतर प्रदर्शन करेगा।

+2

eek microbenchmark! http://stackoverflow.com/q/504103/116509 – artbristol

+1

@artbristol हाँ मुझे पता है कि मैंने क्यों ** ** की तरह ** पर जोर दिया;) – assylias

+0

इनपुट पैरामीटर 'java.util.Date' के लिए है,' डेटटाइम 'नहीं – artbristol

1

withTime() कक्षा DateTime की विधि का उपयोग करने के बारे में, ताकि आपको केवल एक कॉल करना पड़े?

private DateTime createDateTime(java.util.Date date, org.joda.time.Chronology chronology) { 
    DateTime dateTime = new DateTime(date, chronology); 
    return dateTime.withTime(dateTime.getHourOfDay(), 0, 0, 0); 
} 
+0

अनजाने में यह ** धीमा चलाने के लिए ** लगता है ... – assylias

+0

@assylias आह हाँ, मुझे लगता है कि यह आपके परीक्षण मामलों में से एक है। यह वास्तव में अजीब बात है, खासकर यदि आप जोडा समय के स्रोत कोड को देखते हैं तो यह देखने के लिए कि वास्तव में उन सभी के साथ क्या है ...() 'विधियां करते हैं। – Jesper

+0

या शायद जिस तरह से मैं इसका परीक्षण करता हूं, जो थोड़ा सा सरल है! – assylias

3

विधि dateTime.hourOfDay().roundFloorCopy() एक भी विधि कॉल में शून्य करने के लिए मिनट, सेकंड और मिली दौर जाना चाहिए (और सिफारिश की रास्ता है अगर प्रदर्शन एक मुद्दा नहीं है)। हालांकि, मिलिस पर सीधे मॉड्यूल को कॉल करने से तेज़ होने की संभावना नहीं है।

संबंधित मुद्दे