जावा में माइक्रोसेकंड में वर्तमान समय


104

यूनिक्स प्रणाली पर, जावा में माइक्रोसेकंड स्तर सटीकता के साथ टाइमस्टैम्प प्राप्त करने का एक तरीका है? कुछ ऐसा है C का gettimeofdayफंक्शन।


6
ध्यान रखें कि कंप्यूटर घड़ियों को सटीकता के उस स्तर के आसपास कहीं भी सेट नहीं किया जाता है - विभिन्न कंप्यूटरों पर दो घड़ियों आमतौर पर कम से कम कुछ मिलीसेकंड तक भिन्न होती हैं, जब तक कि आप उच्च सटीकता सिंक्रनाइज़ेशन प्रक्रिया स्थापित करने में कुछ प्रयास नहीं करते हैं। (जब ऐसी बात शारीरिक रूप से भी संभव हो)। मैं कल्पना नहीं कर सकता कि माइक्रोसेकंड के लिए कंप्यूटर का समय जानने के लिए क्या बिंदु होगा। (यदि आप एक अंतराल को मापने की कोशिश कर रहे हैं जो एक कंप्यूटर पर ठीक है, तो निश्चित रूप से, यह पूरी तरह से उचित है, लेकिन आपको पूर्ण टाइमस्टैम्प की आवश्यकता नहीं है।)
डेविड जेड

2
इसके अलावा, यूनिक्स / लिनक्स के कुछ संस्करण केवल माइक्रोसेकंड क्षेत्र में 1 मिलीसेकंड या 10 मिलीसेकंड ग्रैन्युलैरिटी लौटाते हैं।
स्टीफन सी

अप्रत्यक्ष तरीका जेडीबीसी के माध्यम से होता है , अगर डेटाबेस जैसे कि पोस्टग्रैज से जुड़ा होता है जो माइक्रोसेकंड में वर्तमान समय को कैप्चर करता है।
तुलसी बॉर्क

2
जावा 9 और बाद में:Instant.now()
बेसिल बोर्के

एपोच के बाद से माइक्रोसेकंड की गणना करने के लिए तत्काल का उपयोग करें: val instant = Instant.now(); val currentTimeMicros = instant.getEpochSecond() * 1000_000 + instant.getNano() / 1000;
माइकल एम।

जवाबों:


148

नहीं, जावा में वह क्षमता नहीं है।

इसमें System.nanoTime () है, लेकिन यह सिर्फ कुछ पहले से ज्ञात समय से ऑफसेट देता है। इसलिए जब तक आप इससे पूर्ण संख्या नहीं ले सकते, आप इसे नैनोसेकंड (या उच्चतर) सटीकता को मापने के लिए उपयोग कर सकते हैं।

ध्यान दें कि JavaDoc का कहना है कि whilst यह नैनोसेकंड सटीक प्रदान करता है, इसका मतलब यह नहीं है कि नैनोसेकंड सटीकता। तो वापसी मूल्य के कुछ बड़े मापांक लें।


3
कोई यह अनुमान लगाएगा कि जावा के पास कोई getTimeInMicroseconds () 1) सटीकता नहीं है जो कई प्लेटफार्मों पर उपलब्ध नहीं है, 2) माइक्रोसेकंड कॉल में मिलीसेकंड सटीकता वापस करने पर अनुप्रयोग पोर्टेबिलिटी समस्या होती है।
स्टीफन सी

9
लिनक्स पर, System.nanoTime () कॉल clock_gettime (CLOCK_MONOTONIC, _)। ब्रायन ऑक्सले ने इस डली को खोजने के लिए जावा के सोर्स कोड में खोदा।
डेविड वेबर

7
यह उत्तर अब पुराना हो चुका है । JavaJ के OpenJDK और Oracle कार्यान्वयन एक नए कार्यान्वयन के साथ आते हैं, Clockजो वर्तमान क्षण को मिलीसेकंड से अधिक रिज़ॉल्यूशन के साथ कैप्चर करने के लिए प्रदान करता है। एक मैकबुक प्रो रेटिना पर मुझे माइक्रोसेकंड (दशमलव अंश के छह अंक) में वर्तमान समय मिल रहा है। वास्तविक परिणाम और सटीकता होस्ट कंप्यूटर के अंतर्निहित क्लॉक हार्डवेयर पर निर्भर करते हैं।
बेसिल बोर्के

1
@BasilBourque बहुत सारे सिस्टम अभी भी जावा 8 पर चलते हैं या इससे पहले भी क्योंकि उन्हें माइग्रेट करने की कोई आवश्यकता नहीं है। हालांकि उत्तर पुराना है, फिर भी यह उपयोगी है।
ड्रैगस

1
@Dragas वास्तव में, वहाँ हैं उन्हें विस्थापित करने के लिए एक की जरूरत है ... के रूप में इस प्रश्न से पूछा माइक्रोसेकंड में वर्तमान समय प्राप्त करने के लिए किया जाना है।
तुलसी बॉर्क

78

tl; डॉ

जावा 9 और बाद में: वर्तमान क्षण को कैप्चर करते समय नैनोस्कॉन्ड्स रिज़ॉल्यूशन तक। यह दशमलव अंश का 9 अंक है।

Instant.now()   

2017-12-23T12: 34: 56.123456789Z

माइक्रोसेकंड तक सीमित करने के लिए , काटें

Instant                // Represent a moment in UTC. 
.now()                 // Capture the current moment. Returns a `Instant` object. 
.truncatedTo(          // Lop off the finer part of this moment. 
    ChronoUnit.MICROS  // Granularity to which we are truncating. 
)                      // Returns another `Instant` object rather than changing the original, per the immutable objects pattern. 

2017-12-23T12: 34: 56.123456Z

व्यवहार में, आप देखेंगे कि केवल माइक्रोसेकंड .nowको समकालीन पारंपरिक कंप्यूटर हार्डवेयर घड़ियों के साथ कैप्चर किया गया है जो नैनोसेकंड में सटीक नहीं हैं ।

विवरण

अन्य उत्तर कुछ हद तक जावा 8 के रूप में पुराने हैं।

java.time

जावा 8 और बाद में जावा.टाइम फ्रेमवर्क के साथ आता है । ये नई कक्षाएं जावा के शुरुआती संस्करणों जैसे कि java.util.Date/.Calendar और java.text.SimpleDateFormat के साथ भेजे गए त्रुटिपूर्ण परेशान करने वाले दिनांक-समय वर्गों को दबा देती हैं। जेएसआर 310 द्वारा फ्रेमवर्क को परिभाषित किया गया है , जो थोडा-एक्स्ट्रा प्रोजेक्ट द्वारा विस्तारित, जोडा-टाइम से प्रेरित है ।

Java.time में कक्षाएं नैनोसेकंड के लिए हल होती हैं , पुरानी तारीखों की कक्षाओं और जोडा-टाइम दोनों द्वारा उपयोग किए गए मिलीसेकंड की तुलना में बहुत अधिक महीन । और प्रश्न में पूछे गए माइक्रोसेकंड से बेहतर है ।

यहां छवि विवरण दर्ज करें

Clock कार्यान्वयन

जबकि java.time कक्षाएं नैनोसेकंड में मूल्यों का प्रतिनिधित्व करने वाले डेटा का समर्थन करती हैं, फिर भी कक्षाएं नैनोसेकंड में मान उत्पन्न नहीं करती हैं। now()विधियों, पुराने तिथि-समय वर्ग के रूप में वही पुरानी घड़ी कार्यान्वयन का उपयोग System.currentTimeMillis()। हमारे पास Clockjava.time में नया इंटरफ़ेस है लेकिन उस इंटरफ़ेस के लिए कार्यान्वयन वही पुरानी मिलीसेकंड घड़ी है।

इसलिए आप ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )एक भिन्नात्मक दूसरे के नौ अंकों को देखने के परिणाम के शाब्दिक प्रतिनिधित्व को प्रारूपित कर सकते हैं, लेकिन केवल पहले तीन अंकों की संख्या इस तरह होगी:

2017-12-23T12:34:56.789000000Z

जावा 9 में नई घड़ी

जावा 9 के ओपनजेडके और ओरेकल कार्यान्वयनों ने Clockबारीक बारीकियों के साथ एक नया डिफ़ॉल्ट कार्यान्वयन किया है, जो जावा.टाइम कक्षाओं की पूर्ण नैनोसेकंड क्षमता तक है।

OpenJDK समस्या देखें, java.time.Clock.systemUTC () के कार्यान्वयन की सटीकता बढ़ाएँ । उस मुद्दे को सफलतापूर्वक लागू किया गया है।

2017-12-23T12:34:56.123456789Z

MacOS Sierra के साथ एक मैकबुक प्रो (रेटिना, 15-इंच, लेट 2013) पर, मुझे माइक्रोसेकंड (दशमलव अंश के छह अंक तक) में वर्तमान क्षण मिलता है।

2017-12-23T12:34:56.123456Z

हार्डवेयर घड़ी

याद रखें कि एक नए महीन Clockकार्यान्वयन के साथ, आपके परिणाम कंप्यूटर द्वारा भिन्न हो सकते हैं। जावा वर्तमान क्षण जानने के लिए अंतर्निहित कंप्यूटर हार्डवेयर की घड़ी पर निर्भर करता है।

  • हार्डवेयर घड़ियों का संकल्प व्यापक रूप से भिन्न होता है। उदाहरण के लिए, यदि किसी विशेष कंप्यूटर की हार्डवेयर घड़ी केवल माइक्रोसेकंड ग्रैन्युलैरिटी का समर्थन करती है , तो किसी भी उत्पन्न तिथि-समय के मानों में पिछले तीन अंकों के शून्य अंश के साथ केवल छह अंकों का अंश होगा।
  • हार्डवेयर घड़ियों की सटीकता व्यापक रूप से भिन्न होती है। सिर्फ इसलिए कि एक घड़ी एक सेकंड के दशमलव अंश के कई अंकों के साथ एक मूल्य उत्पन्न करती है, उन अंकों को गलत किया जा सकता है, बस सन्निकटन, वास्तविक समय से adrift जैसा कि एक परमाणु घड़ी से पढ़ा जा सकता है । दूसरे शब्दों में, सिर्फ इसलिए कि आप दशमलव चिह्न के दाईं ओर अंकों का एक गुच्छा देखते हैं, इसका मतलब यह नहीं है कि आप इस तरह के रीडिंग के बीच बीत चुके समय को उस मिनट की डिग्री के लिए सही मान सकते हैं।

वे नैनोसेकंड का समाधान कर सकते हैं लेकिन वे अभी भी System.currentTimeMillis पर आधारित हैं, इसलिए वे अंत में 0s का एक गुच्छा जोड़ते हैं। यदि आप माइक्रो / नैनो सेकंड में समय प्राप्त करने की कोशिश कर रहे हैं तो उपयोगकर्ता बिल्कुल भी मदद नहीं करता है, उपयोगकर्ता केवल मैन्युअल रूप से मिलीसेकंड में 0s जोड़ सकता है।
annedroiid

@ बरदोईद ने मुझे अपने उत्तर में कवर किया। जावा 8 में आप नैनोसेकंड रिज़ॉल्यूशन वाले क्षणों को स्टोर कर सकते हैं, लेकिन वर्तमान क्षण पर कब्जा करना केवल मिलीसेकंड में है। के नए कार्यान्वयन के साथ जावा 9 में बने रहे Clock। फिर भी, जावा 8 में java.time क्लासेस अन्य स्रोतों द्वारा कैप्चर किए गए मानों जैसे कि पोस्टग्रॉउंड डेटाबेस पर माइक्रोसेकंड के लिए मददगार हैं। लेकिन माइक्रोसेकंड और नैनोसेकंड रेंज में मूल्यों की अशुद्धि से सावधान रहें; आम कंप्यूटर हार्डवेयर एक हार्डवेयर घड़ी ट्रैकिंग समय नहीं ले सकता है जो सटीक रूप से हो। भिन्नात्मक दूसरे के छह या नौ अंकों वाला मान सत्य नहीं हो सकता है।
बेसिल बोर्क

क्या यह ChronoUnit.MICROS नहीं है ?
रोलैंड

@ रोलैंड हाँ, अब तय है, धन्यवाद। FYI करें, स्टैक ओवरफ्लो पर आपको इस तरह की त्रुटि को ठीक करने के लिए एक उत्तर को सीधे संपादित करने के लिए आमंत्रित किया जाता है।
बेसिल बोर्क

55

आप उपयोग कर सकते हैं System.nanoTime():

long start = System.nanoTime();
// do stuff
long end = System.nanoTime();
long microseconds = (end - start) / 1000;

नैनोसेकंड में समय पाने के लिए लेकिन यह एक सख्ती से संबंधित उपाय है। इसका कोई निरपेक्ष अर्थ नहीं है। यह केवल दूसरे नैनो बार की तुलना करने के लिए उपयोगी है, यह मापने के लिए कि कुछ करने में कितना समय लगा।


14

जैसा कि अन्य पोस्टर पहले ही संकेत दे चुके हैं; आपका सिस्टम क्लॉक शायद माइक्रोसेकंड तक वास्तविक दुनिया के समय तक सिंक्रनाइज़ नहीं है। फिर भी, वर्तमान दीवार के समय को इंगित करने और चीजों की अवधि को मापने / मापने के लिए दोनों के लिए हाइब्रिड के रूप में माइक्रोसेकंड सटीक टाइमस्टैम्प उपयोगी हैं।

मैं "2012-10-21 19: 13: 45.267128" जैसे टाइमस्टैम्प का उपयोग करके लॉग फ़ाइलों को लिखे गए सभी घटनाओं / संदेशों को लेबल करता हूं। ये दोनों तब होते हैं जब यह ("दीवार" समय) हुआ, और इसका उपयोग लॉग फ़ाइल में इस और अगली घटना (माइक्रोसेकंड में सापेक्ष अंतर) के बीच की अवधि को मापने के लिए भी किया जा सकता है ।

इसे प्राप्त करने के लिए, आपको System.currentTimeMillis () को System.nanoTime () के साथ लिंक करना होगा और उस क्षण से आगे System.nanoTime () के साथ विशेष रूप से काम करना होगा। उदाहरण कोड:

/**
 * Class to generate timestamps with microsecond precision
 * For example: MicroTimestamp.INSTANCE.get() = "2012-10-21 19:13:45.267128"
 */ 
public enum MicroTimestamp 
{  INSTANCE ;

   private long              startDate ;
   private long              startNanoseconds ;
   private SimpleDateFormat  dateFormat ;

   private MicroTimestamp()
   {  this.startDate = System.currentTimeMillis() ;
      this.startNanoseconds = System.nanoTime() ;
      this.dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") ;
   }

   public String get()
   {  long microSeconds = (System.nanoTime() - this.startNanoseconds) / 1000 ;
      long date = this.startDate + (microSeconds/1000) ;
      return this.dateFormat.format(date) + String.format("%03d", microSeconds % 1000) ;
   }
}

5
विचार अच्छा है, लेकिन आपको हर बार फिर से सिंक्रनाइज़ करना होगा। सिस्टम टाइम (करंट टाइम) और सीपीयू क्लॉक (नैनो टाइम) सिंक में नहीं हैं, क्योंकि वे अक्सर अलग हार्डवेयर घड़ियों पर आधारित होते हैं। इसके अतिरिक्त, आपके ऑपरेटिंग सिस्टम का समय सर्वर, सिस्टम घड़ी को बाहरी समय स्रोत के साथ फिर से सिंक्रनाइज़ करता है, यदि उपलब्ध हो। इसलिए, आपका प्रतीत होता है बहुत सटीक वर्ग समय टिकटों का उत्पादन करेगा जो बंद हो सकता है!
h2stein

3
यह कोड थ्रेड सुरक्षित प्रतीत नहीं होता है। दो युगपत कॉल MicroTimestamp.INSTANCE.get()समस्याग्रस्त हो सकते हैं।
अहमद

@ क्या आपको लगता है कि कोड थ्रेड सुरक्षित नहीं है? get()सदस्य चर को अद्यतन करने वाली विधि में कुछ भी नहीं है ; यह केवल अस्थायी स्थानीय चर का उपयोग करता है।
जेसन स्मिथ

6

आप शायद एक ऐसा घटक बना सकते हैं जो System.nanoTime () और System.currentTimeMillis () के बीच ऑफसेट को निर्धारित करता है और प्रभावी रूप से युग के बाद से नैनोसेकंड प्राप्त करता है।

public class TimerImpl implements Timer {

    private final long offset;

    private static long calculateOffset() {
        final long nano = System.nanoTime();
        final long nanoFromMilli = System.currentTimeMillis() * 1_000_000;
        return nanoFromMilli - nano;
    }

    public TimerImpl() {
        final int count = 500;
        BigDecimal offsetSum = BigDecimal.ZERO;
        for (int i = 0; i < count; i++) {
            offsetSum = offsetSum.add(BigDecimal.valueOf(calculateOffset()));
        }
        offset = (offsetSum.divide(BigDecimal.valueOf(count))).longValue();
    }

    public long nowNano() {
        return offset + System.nanoTime();
    }

    public long nowMicro() {
        return (offset + System.nanoTime()) / 1000;
    }

    public long nowMilli() {
        return System.currentTimeMillis();
    }
}

मेरी मशीन पर परीक्षण के बाद काफी अच्छे परिणाम मिलते हैं।

    final Timer timer = new TimerImpl();
    while (true) {
        System.out.println(timer.nowNano());
        System.out.println(timer.nowMilli());
    }

अंतर + -3ms की सीमा में दोलन करने लगता है। मुझे लगता है कि एक ऑफसेट गणना को थोड़ा और मोड़ सकता है।

1495065607202174413
1495065607203
1495065607202177574
1495065607203
...
1495065607372205730
1495065607370
1495065607372208890
1495065607370
...

2

यदि आप लिनक्स में रुचि रखते हैं: यदि आप स्रोत कोड को "currentTimeMillis ()" से निकालते हैं, तो आप देखेंगे कि लिनक्स पर, यदि आप इस विधि को कहते हैं, तो यह एक माइक्रोसेकंड समय वापस मिल जाता है। हालाँकि जावा तब माइक्रोसेकंड को छोटा कर देता है और आपको वापस मिलिसकंड करता है। यह आंशिक रूप से है क्योंकि जावा को क्रॉस प्लेटफॉर्म होना चाहिए इसलिए विशेष रूप से लिनक्स के लिए तरीके प्रदान करना दिन में एक बड़ा नो-नो बैक था (याद रखें कि क्रूड्डी सॉफ्ट सपोर्ट 1.6 बैकवर्ड से सपोर्ट करता है ?!)। ऐसा इसलिए भी है, क्योंकि जब आप घड़ी देखते हैं तो आप लिनक्स में माइक्रोसेकंड वापस दे सकते हैं, इसका मतलब यह नहीं है कि यह समय की जांच करने के लिए अच्छा होगा। माइक्रोसेकंड के स्तर पर, आपको यह जानना होगा कि NTP आपके समय का अहसास नहीं करा रहा है और विधि कॉल के दौरान आपकी घड़ी बहुत अधिक नहीं चली है।

इसका मतलब है, सिद्धांत रूप में, लिनक्स पर, आप एक जेएनआई आवरण लिख सकते हैं जो सिस्टम पैकेज में एक जैसा है, लेकिन माइक्रोसेकंड को छोटा नहीं करता है।


2

एक "त्वरित और गंदे" समाधान जो मैं अंततः साथ गया:

TimeUnit.NANOSECONDS.toMicros(System.nanoTime());

अपडेट करें:

मैं मूल रूप से System.nanoTime के साथ गया था, लेकिन फिर मुझे पता चला कि इसका उपयोग केवल बीते हुए समय के लिए किया जाना चाहिए, मैंने अंततः अपने कोड को मिलीसेकंड या कुछ स्थानों पर उपयोग करने के लिए बदल दिया:

TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());

लेकिन यह सिर्फ मूल्य के अंत में शून्य जोड़ देगा (माइक्रो = मिलिस * 1000)

इस उत्तर को "चेतावनी संकेत" के रूप में यहाँ छोड़ दें यदि कोई और व्यक्ति नैनो टाइम के बारे में सोचता है :)


1
दस्तावेज़ स्पष्ट रूप से कहता है नहीं का उपयोग System.nanoTimeदीवार-घड़ी समय के लिए: "यह विधि केवल बीता हुआ समय को मापने के लिए इस्तेमाल किया जा सकता है और सिस्टम या दीवार-घड़ी ऐसी कोई भी धारणा से संबंधित नहीं है।"
बेसिल बोर्के

1
@BasilBourque आप सही हैं, यह लिखने के बाद मुझे अंततः पता चला और अपना कोड बदल गया लेकिन यहाँ अपडेट करना भूल गया, टिप्पणी के लिए धन्यवाद!
कीसार

2

जावा एनम के माध्यम से माइक्रोसेकंड का समर्थन करता है TimeUnit

यहाँ जावा डॉक है: Enum TimeUnit

आप इस तरह से जावा में माइक्रोसेकंड प्राप्त कर सकते हैं:

long microsenconds = TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis());

उदाहरण के लिए, आप माइक्रोसेकंड को दूसरी समय इकाइयों में भी बदल सकते हैं:

long seconds = TimeUnit.MICROSECONDS.toSeconds(microsenconds);

यह सही नहीं है, आपको माइक्रो रिज़ॉल्यूशन / लंबाई में समय मिलेगा, लेकिन समय हमेशा केवल MILI सटीकता के साथ होगा (जिसका अर्थ है कि अंतिम 3 अंक हमेशा 0 होंगे)।
मिशालक्स

0

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

String timestamp = new String();
do {
    timestamp = String.valueOf(MicroTimestamp.INSTANCE.get());
    item.setTimestamp(timestamp);
} while(lasttimestamp.equals(timestamp));
lasttimestamp = item.getTimestamp();

0

युग के बाद से माइक्रोसेकंड की गणना करने के लिए त्वरित का उपयोग करें:

val instant = Instant.now();
val currentTimeMicros = instant.getEpochSecond() * 1000_000 + instant.getNano() / 1000;


-3

यहाँ कैसे एक UnsignLong वर्तमान टाइमस्टैम्प बनाने के लिए एक उदाहरण है:

UnsignedLong current = new UnsignedLong(new Timestamp(new Date().getTime()).getTime());

2
गलत जवाब। Java.util.Date क्लास में मिलीसेकंड का रिज़ॉल्यूशन होता है, प्रश्न में निर्दिष्ट माइक्रोसेकंड नहीं। Java.sql.Timestamp बनाना हवा से अतिरिक्त डेटा नहीं खींचता है।
बेसिल बोर्के
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.