Java.Time.LocalDateTime এবং java.util.Date- র মধ্যে রূপান্তর করা


484

জাভা 8 এর তারিখ এবং সময়টির জন্য সম্পূর্ণ নতুন এপিআই রয়েছে। এই এপিআই-এর সর্বাধিক দরকারী ক্লাসগুলির মধ্যে LocalDateTimeএকটি সময়-সময়-স্বতন্ত্র তারিখের সাথে-সময় মান রাখার জন্য।

এই লক্ষ্যে সম্ভবত উত্তরাধিকার শ্রেণিটি ব্যবহার করে কয়েক মিলিয়ন লাইন কোড রয়েছে java.util.Date। যেমন, পুরানো এবং নতুন কোডের ইন্টারফেস করার সময় দুজনের মধ্যে রূপান্তর করার প্রয়োজন হবে। যেহেতু এটি সম্পাদন করার জন্য কোনও প্রত্যক্ষ পদ্ধতি নেই বলে মনে হচ্ছে, এটি কীভাবে সম্ভব?




উত্তর:


706

সংক্ষিপ্ত উত্তর:

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());

ব্যাখ্যা: ( সম্পর্কে এই প্রশ্নের উপর ভিত্তি করে LocalDate)

এর নাম সত্ত্বেও, java.util.Dateসময়রেখায় একটি তাত্ক্ষণিক প্রতিনিধিত্ব করে, "তারিখ" নয়। বস্তুর মধ্যে সংরক্ষিত প্রকৃত তথ্য হ'ল long1970-01-01T00: 00Z (1970 জিএমটি / ইউটিসি শুরুতে মধ্যরাত) সাল থেকে মিলিসেকেন্ডের একটি গণনা।

java.util.Dateজেএসআর -310 এর সমমানের শ্রেণি হ'ল Instant, এইভাবে রূপান্তরটি সরবরাহের জন্য সুবিধাজনক পদ্ধতি রয়েছে:

Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);

একটি java.util.Dateউদাহরণ হিসেবে বলা যায় সময় অঞ্চল কোন ধারণা আছে। আপনি যদি কল toString()করেন তবে এটি অদ্ভুত বলে মনে হতে পারে java.util.Dateকারণ toStringসময় অঞ্চলটির সাথে সম্পর্কিত the তবে সেই পদ্ধতিটি স্ট্রিং সরবরাহ করতে ফ্লাইতে জাওয়ার ডিফল্ট সময় অঞ্চলটি ব্যবহার করে। সময় অঞ্চলটি আসল অবস্থার অংশ নয় java.util.Date

একটিতে Instantসময়-অঞ্চল সম্পর্কে কোনও তথ্য থাকে না। সুতরাং, একটি Instantথেকে স্থানীয় তারিখ-সময় রূপান্তর করার জন্য একটি সময়-অঞ্চল নির্দিষ্ট করা প্রয়োজন। এটি ডিফল্ট অঞ্চল হতে পারে - ZoneId.systemDefault()- বা এটি এমন একটি সময়-অঞ্চল হতে পারে যা আপনার অ্যাপ্লিকেশন নিয়ন্ত্রণ করে, যেমন ব্যবহারকারীর পছন্দসমূহ থেকে সময়-অঞ্চল। LocalDateTimeএকটি সুবিধাজনক কারখানা পদ্ধতি রয়েছে যা তাত্ক্ষণিক এবং সময় অঞ্চল উভয়ই গ্রহণ করে:

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());

বিপরীতে, LocalDateTimeসময়-অঞ্চলটি atZone(ZoneId)পদ্ধতিটি কল করে নির্দিষ্ট করা হয় । ZonedDateTimeতারপর সরাসরি পরিবর্তিত করা যায় Instant:

LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());

নোট থেকে রুপান্তরের যে LocalDateTimeকরতে ZonedDateTimeঅপ্রত্যাশিত আচরণের পরিচয় করিয়ে দিতে সম্ভাবনা রয়েছে। এটি কারণ দিবালোক সংরক্ষণের কারণে প্রতিটি স্থানীয় তারিখের সময় উপস্থিত থাকে না। শরত্কালে / শরতে, স্থানীয় সময়রেখায় একটি ওভারল্যাপ থাকে যেখানে একই স্থানীয় তারিখ-সময় দু'বার ঘটে। বসন্তে, একটি ফাঁক আছে, যেখানে এক ঘন্টা অদৃশ্য হয়ে যায়। atZone(ZoneId)রূপান্তরটি কী করবে তার আরও সংজ্ঞা পেতে জাভাদোক দেখুন ।

সংক্ষিপ্তসার, আপনি যদি java.util.Dateকোনও পথে একবার LocalDateTimeএবং java.util.Dateএকবারে ভ্রমণ করেন তবে দিবালোক সংরক্ষণের সময়টির কারণে আপনি অন্যরকম তাত্ক্ষণিক ঘটনাটি শেষ করতে পারেন।

অতিরিক্ত তথ্য: আরও একটি পার্থক্য রয়েছে যা খুব পুরানো তারিখগুলিকে প্রভাবিত করে। java.util.Dateগ্রেগরিয়ান পরিবর্তে জুলিয়ান ক্যালেন্ডার ব্যবহার করার আগে তারিখগুলির সাথে 15 ই অক্টোবর 1582-এ পরিবর্তিত একটি ক্যালেন্ডার ব্যবহার করে। বিপরীতে, java.time.*সর্বকালের জন্য আইএসও ক্যালেন্ডার সিস্টেম (গ্রেগরিয়ান সমতুল্য) ব্যবহার করে। বেশিরভাগ ব্যবহারের ক্ষেত্রে, আইএসও ক্যালেন্ডার সিস্টেমটি আপনি যা চান তা হ'ল, তবে 1582 সালের আগের তারিখগুলির তুলনা করার সময় আপনি অদ্ভুত প্রভাব দেখতে পাবেন।


5
পরিষ্কার ব্যাখ্যার জন্য অনেক ধন্যবাদ। বিশেষত কেন জন্য java.util.Dateসময় অঞ্চল অন্তর্ভুক্ত নয়, তবে এটি মুদ্রণ করুন toString()। ইভেন্টের অফিসিয়াল ডকুমেন্টেশন আপনার পোস্ট করার সাথে এটি পরিষ্কারভাবে বলে না।
চেরি

সতর্কতা: LocalDateTime.ofInstant(date.toInstant()... যেমন নির্গতভাবে প্রত্যাশা করা হয় তেমন আচরণ করে না। উদাহরণস্বরূপ এই পদ্ধতির ব্যবহার new Date(1111-1900,11-1,11,0,0,0);হয়ে উঠবে 1111-11-17 23:53:28java.sql.Timestamp#toLocalDateTime()আপনি যদি 1111-11-11 00:00:00পূর্বের উদাহরণে ফলাফলের প্রয়োজন হয় তবে এর বাস্তবায়নটি একবার দেখুন ।
কুকুর

2
আমি খুব পুরানো তারিখগুলি সম্পর্কে একটি বিভাগ যুক্ত করেছি (1582 পূর্ব)। এফডাব্লুআইডাব্লু, আপনার প্রস্তাবিত ফিক্সটি ভুল হতে পারে, যেমন 1111-11-11 11 java.util.Date বিভিন্ন ইতিহাসের ক্যালেন্ডারের সিস্টেমের কারণে জাভা.টাইমে 1111-11-18 হিসাবে ইতিহাসের একই প্রকৃত দিন ( 1900 এর আগে অনেক টাইম জোনে ঘটে)
জোদাস্টেফেন

2
এছাড়াও java.sql.Date#toInstantএকটি নিক্ষেপ মূল্য মূল্য UnsupportedOperationException। সুতরাং toInstantকোনও রো-ম্যাপার চালু করবেন না java.sql.ResultSet#getDate
লাজারবাস

132

আমি এখানে যা এলাম তা এখানে এসেছে (এবং সমস্ত তারিখের সময়ের মত এটি সম্ভবত কিছু অদ্ভুত টাইমজোন-লিপিয়ার-ডে আলোর সামঞ্জস্যের ভিত্তিতে অস্বীকৃত হতে চলেছে: ডি)

রাউন্ড-ট্রিপিং: Date<<->>LocalDateTime

প্রদত্ত: Date date = [some date]

(1) LocalDateTime<< Instant<<Date

    Instant instant = Instant.ofEpochMilli(date.getTime());
    LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

(২) Date<< Instant<<LocalDateTime

    Instant instant = ldt.toInstant(ZoneOffset.UTC);
    Date date = Date.from(instant);

উদাহরণ:

প্রদত্ত:

Date date = new Date();
System.out.println(date + " long: " + date.getTime());

(1) LocalDateTime<< Instant<< Date:

এর Instantথেকে তৈরি করুন Date:

Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);

Dateথেকে তৈরি করুন Instant(প্রয়োজনীয় নয়, তবে উদাহরণের জন্য):

date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());

LocalDateTimeথেকে তৈরি করুনInstant

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);

(২) Date<< Instant<<LocalDateTime

এর Instantথেকে তৈরি করুন LocalDateTime:

instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);

এর Dateথেকে তৈরি করুন Instant:

date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());

আউটপুটটি হ'ল:

Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

Instant from Date:
2013-11-01T14:13:04.574Z

Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

LocalDateTime from Instant:
2013-11-01T14:13:04.574

Instant from LocalDateTime:
2013-11-01T14:13:04.574Z

Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574

2
@ স্কটব আপনি কি আমাকে বা যে প্রশ্নটি উত্থাপন করেছেন তাকে সম্বোধন করছেন? আমার চিন্তা হিসাবে, ভাল, এটি হবে চমৎকার রূপান্তর JDK 8 API এ স্পষ্টভাবে বিবৃত হয়েছে - তারা অন্তত যে কাজ করতে পারে। যাই হোক না কেন, প্রচুর লাইব্রেরি রয়েছে যা নতুন জাভা -8 বৈশিষ্ট্যগুলিকে অন্তর্ভুক্ত করতে এবং এটি কীভাবে করা যায় তা জরুরী বলে পুনরায় ফ্যাক্টর করা হবে।
সমন্বয়কারী

4
@ স্কটব তৃতীয় পক্ষের মামলাটি কেন অস্বাভাবিক হবে? এটি অভিশাপ সাধারণ। একটি উদাহরণ: জেডিবিসি 4 এবং তার চেয়ে কম (আশা করি 5 নয়)।
রমন

5
জেনারেল জেএসআর -310 নিয়ম হিসাবে, ইউপ-মিলিস ব্যবহার করে প্রকারের মধ্যে রূপান্তর করার দরকার নেই। অবজেক্ট ব্যবহার করে আরও ভাল বিকল্প বিদ্যমান, নীচে আমার পুরো উত্তরটি দেখুন। উপরের উত্তরটি কেবলমাত্র সম্পূর্ণরূপে বৈধ যদি ইউটিসির মতো জোন অফসেট ব্যবহার করা হয় - উত্তরের কিছু অংশ আমেরিকা / নিউ_ইয়র্কের মতো পূর্ণ সময়-অঞ্চলের জন্য কাজ করবে না।
জোদাস্টেফেন

2
পরিবর্তে Instant.ofEpochMilli(date.getTime())করdate.toInstant()
ছাগল

1
@ ছাগল toInstant()দেখতে সুন্দর লাগছে , ব্যর্থতা ব্যতীত java.sql.Date, আরজিজি! সুতরাং এটি অবশেষে ব্যবহার করা সহজ Instant.ofEpochMilli(date.getTime())
ভাদ্পিপ

22

আপনার যদি একটি ডিফল্ট টাইমজোন প্রয়োজন বলে নিশ্চিত হন তবে আরও অনেক সুবিধাজনক উপায়:

Date d = java.sql.Timestamp.valueOf( myLocalDateTime );

25
অবশ্যই, এটি সহজ, তবে আমি কমপক্ষে আইএমএইচওর সাথে সাধারণ ডেট হ্যান্ডলিংয়ের সাথে জেডিবিসি সম্পর্কিত সামগ্রীগুলি পছন্দ করি না।
এনরিকো গিউরিন

9
আমি দুঃখিত, এটি একটি সাধারণ সমস্যার ভয়াবহ সমাধান। এটি 5 টি অলিম্পিক লোগোতে রিংয়ের সংখ্যার সমান সংজ্ঞা দেওয়ার মতো।
ম্যাডব্রেকস

7

নতুন এপিআই লোকালডেটটাইম থেকে java.util.date রূপান্তর করার সময় নিম্নলিখিতটি কাজ করছে বলে মনে হচ্ছে:

Date.from(ZonedDateTime.of({time as LocalDateTime}, ZoneId.systemDefault()).toInstant());

বিপরীত রূপান্তরটি (আশা করা যায়) একইভাবে অর্জন করা যেতে পারে ...

আশা করি এটা সাহায্য করবে...


5

সবকিছু এখানে: http://blog.progs.be/542/date-to-java-time time

"রাউন্ড-ট্রিপিং" সহ উত্তরটি সঠিক নয়: আপনি যখন করবেন

LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

যদি আপনার সিস্টেমের সময় অঞ্চলটি ইউটিসি / জিএমটি না হয়, আপনি সময় পরিবর্তন করুন!


কেবলমাত্র যদি আপনি বছরে 1 ঘন্টা সময় করেন, শরত্কালে, লোকালডেটটাইম থেকে দুবার ওভারল্যাপ হয়। বসন্তের ফরোয়ার্ড সরানো কোনও সমস্যার কারণ হয় না। বেশিরভাগ সময় উভয় দিক সঠিকভাবে রূপান্তরিত করে।
ডেভিড


3

আমি নিশ্চিত নই যে এটি সর্বাধিক সহজ বা সর্বোত্তম উপায়, বা যদি কোনও সমস্যা রয়েছে তবে তা কার্যকর হয়:

static public LocalDateTime toLdt(Date date) {
    GregorianCalendar cal = new GregorianCalendar();
    cal.setTime(date);
    ZonedDateTime zdt = cal.toZonedDateTime();
    return zdt.toLocalDateTime();
}

static public Date fromLdt(LocalDateTime ldt) {
    ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
    GregorianCalendar cal = GregorianCalendar.from(zdt);
    return cal.getTime();
}

3
সেখানে স্পষ্টভাবে একটি ফাঁদ থেকে চলছে LocalDateTimeকরতে Date। দিবালোক সংরক্ষণের ট্রানজিশনে একটি LocalDateTimeঅস্তিত্বহীন হতে পারে বা দুবার ঘটতে পারে। আপনি প্রতিটি ক্ষেত্রে যা হতে চান তা নিয়ে কাজ করা দরকার।
জন স্কিটি

1
বিটিডাব্লু, GregorianCalendarপুরানো বিশ্রী এপিআই এর অন্তর্ভুক্ত যা নতুন java.timeএপিআই প্রতিস্থাপনের লক্ষ্য নিয়েছে
ভাদজিম

3

আপনি যদি অ্যান্ড্রয়েডে থাকেন এবং থ্রিটেনবিপি ব্যবহার করছেন তবে DateTimeUtilsপরিবর্তে আপনি ব্যবহার করতে পারেন ।

উদা:

Date date = DateTimeUtils.toDate(localDateTime.atZone(ZoneId.systemDefault()).toInstant());

আপনি Date.fromএটি ব্যবহার করতে পারবেন না কারণ এটি কেবল এপিআই 26+ তে সমর্থিত

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