রুবিতে ডেটটাইম এবং সময় থেকে রূপান্তর করুন


132

আপনি রুবিতে ডেটটাইম এবং টাইম অবজেক্টের মধ্যে কীভাবে রূপান্তর করবেন?


1
আমি নিশ্চিত নই যে এটি একটি পৃথক প্রশ্ন হওয়া উচিত, তবে আপনি কীভাবে একটি তারিখ এবং একটি সময়ের মধ্যে রূপান্তর করবেন?
অ্যান্ড্রু গ্রিম

8
গৃহীত এবং সর্বাধিক-রেট করা উত্তরগুলি রুবির আধুনিক সংস্করণগুলির অধীনে আর নির্ভুল নয়। উত্তর দেখুন @theTinMan দ্বারা এবং @PatrickMcKenzie দ্বারা নিচে।
ফ্রোগজ

উত্তর:


50

আপনার দুটি সামান্য ভিন্ন রূপান্তর প্রয়োজন।

থেকে রূপান্তর Time করতে DateTimeআপনি নিম্নলিখিত শ্রেণিটি সংশোধন করতে পারেন:

require 'date'
class Time
  def to_datetime
    # Convert seconds + microseconds into a fractional number of seconds
    seconds = sec + Rational(usec, 10**6)

    # Convert a UTC offset measured in minutes to one measured in a
    # fraction of a day.
    offset = Rational(utc_offset, 60 * 60 * 24)
    DateTime.new(year, month, day, hour, min, seconds, offset)
  end
end

তারিখে অনুরূপ সামঞ্জস্য আপনাকে রূপান্তর DateTime করতে দেয় Time

class Date
  def to_gm_time
    to_time(new_offset, :gm)
  end

  def to_local_time
    to_time(new_offset(DateTime.now.offset-offset), :local)
  end

  private
  def to_time(dest, method)
    #Convert a fraction of a day to a number of microseconds
    usec = (dest.sec_fraction * 60 * 60 * 24 * (10**6)).to_i
    Time.send(method, dest.year, dest.month, dest.day, dest.hour, dest.min,
              dest.sec, usec)
  end
end

নোট করুন যে আপনাকে স্থানীয় সময় এবং জিএম / ইউটিসি সময়ের মধ্যে নির্বাচন করতে হবে।

উপরের দুটি কোড স্নিপেটগুলি ও'রিলির রুবি কুকবুক থেকে নেওয়া হয়েছে । তাদের কোড পুনরায় ব্যবহারের নীতি এতে অনুমতি দেয়।


5
এটি ১.৯-এ ভাঙ্গবে যেখানে ডেটটাইম # সেকেন্ড_ফার্যাকশন এক সেকেন্ডে মিলিসেকেন্ডের সংখ্যা দেয়। 1.9 এর জন্য আপনি ব্যবহার করতে চান: usec = dest.sec_fration * 10 ** 6
dkubb

185
require 'time'
require 'date'

t = Time.now
d = DateTime.now

dd = DateTime.parse(t.to_s)
tt = Time.parse(d.to_s)

13
+1 এটি কার্যকর করার ক্ষেত্রে সবচেয়ে দক্ষ নাও হতে পারে তবে এটি কাজ করে, এটি সংক্ষিপ্ত এবং এটি খুব পঠনযোগ্য।
ওয়াল্ট জোনস

6
দুর্ভাগ্যক্রমে স্থানীয় সময় নিয়ে কাজ করার সময় এটি সত্যিই কাজ করে। আপনি যদি কোনও ডেটটাইম বা সময় দিয়ে আলাদা সময় অঞ্চল দিয়ে শুরু করেন, পার্স ফাংশনটি স্থানীয় সময় অঞ্চলে রূপান্তরিত হবে। আপনি মূলত আসল টাইমজোনটি হারাবেন।
বার্নার্ড

6
রুবি ১.৯.২.২০১৮, তারিখটাইম. পার্স সময় অঞ্চল সংরক্ষণ করে। (আমার কাছে পূর্ববর্তী সংস্করণগুলিতে অ্যাক্সেস নেই)) সময়.পার্স সময় অঞ্চল সংরক্ষণ করে না, কারণ এটি পসিক্স-স্ট্যান্ডার্ড সময়_টাকে উপস্থাপন করে, যা আমি বিশ্বাস করি যে যুগের চেয়ে পূর্বের পার্থক্য believe সময়ের সাথে যে কোনও রূপান্তরটির একই আচরণ হওয়া উচিত।
আনশুল

1
তুমি ঠিক বলছো. ডেটটাইম.পারস 1.9.1 এ কাজ করে তবে টাইম.পার্স নয় ars যাইহোক, এটি কম ত্রুটিযুক্ত প্রবণ (ধারাবাহিক) এবং সম্ভবত ডেটটাইম.নিউ (...) এবং টাইম.নিউ (..) ব্যবহার করা তাত্পর্যপূর্ণ। নমুনা কোডের জন্য আমার উত্তর দেখুন।
বার্নার্ড

1
হাই @anshul আমি বোঝাচ্ছি না আমি বলছি :-)। টাইমজোন তথ্য টাইম.পার্স () ব্যবহার করার সময় রাখা হয় না। এটি পরীক্ষা করা সহজ। উপরের আপনার কোডগুলিতে, কেবলমাত্র d = ডেটটাইম.নোকে ডি = ডেটটাইম.নেউ (2010,01,01, 10,00,00, যুক্তিযুক্ত (-2, 24)) এর সাথে প্রতিস্থাপন করুন। tt এখন তারিখটি আপনার স্থানীয় সময় অঞ্চলে রূপান্তর করবে। আপনি এখনও তারিখ পাটিগণিত করতে পারেন এবং মূল tz তথ্য বাদে সমস্ত কিছুই। এই তথ্যটি তারিখের জন্য একটি প্রসঙ্গ এবং এটি প্রায়শই গুরুত্বপূর্ণ। এখানে দেখুন: stackoverflow.com/questions/279769/…
বার্নার্ড

63

রুবি বাস্তুতন্ত্রের রাষ্ট্র একটি আপডেট হিসাবে, Date, DateTimeএবং Timeএখন বিভিন্ন শ্রেণীর মধ্যে রূপান্তর করতে পদ্ধতি আছে। রুবি ব্যবহার করে 1.9.2+:

pry
[1] pry(main)> ts = 'Jan 1, 2000 12:01:01'
=> "Jan 1, 2000 12:01:01"
[2] pry(main)> require 'time'
=> true
[3] pry(main)> require 'date'
=> true
[4] pry(main)> ds = Date.parse(ts)
=> #<Date: 2000-01-01 (4903089/2,0,2299161)>
[5] pry(main)> ds.to_date
=> #<Date: 2000-01-01 (4903089/2,0,2299161)>
[6] pry(main)> ds.to_datetime
=> #<DateTime: 2000-01-01T00:00:00+00:00 (4903089/2,0,2299161)>
[7] pry(main)> ds.to_time
=> 2000-01-01 00:00:00 -0700
[8] pry(main)> ds.to_time.class
=> Time
[9] pry(main)> ds.to_datetime.class
=> DateTime
[10] pry(main)> ts = Time.parse(ts)
=> 2000-01-01 12:01:01 -0700
[11] pry(main)> ts.class
=> Time
[12] pry(main)> ts.to_date
=> #<Date: 2000-01-01 (4903089/2,0,2299161)>
[13] pry(main)> ts.to_date.class
=> Date
[14] pry(main)> ts.to_datetime
=> #<DateTime: 2000-01-01T12:01:01-07:00 (211813513261/86400,-7/24,2299161)>
[15] pry(main)> ts.to_datetime.class
=> DateTime

1
ডেটটাইম.টো_টাইম একটি তারিখটাইম ফেরায় ... 1.9.3p327 :007 > ts = '2000-01-01 12:01:01 -0700' => "2000-01-01 12:01:01 -0700" 1.9.3p327 :009 > dt = ts.to_datetime => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :010 > dt.to_time => Sat, 01 Jan 2000 12:01:01 -0700 1.9.3p327 :011 > dt.to_time.class => DateTime
জেসি ক্লার্ক

উফ। কেবল উপলব্ধি হয়ে গিয়েছে যে এটি একটি রুবি অন রেল ইস্যু নয় কোনও রুবি ইস্যু নয়: স্ট্যাকওভারফ্লো / প্রশ্ন / ১১১127745৪৪৪/২ । এমনকি তারা 2.x লাইনে এই পদ্ধতির বিরুদ্ধে একটি বাগ ফাইল করেছিল এবং এটি "ঠিক করবে না" চিহ্নিত করেছে। ভয়াবহ সিদ্ধান্ত আইএমএইচও। রেলের আচরণ সম্পূর্ণরূপে অন্তর্নিহিত রুবি ইন্টারফেসটি ভেঙে দেয়।
জেসি ক্লার্ক 21

12

দুর্ভাগ্যক্রমে, DateTime.to_time, Time.to_datetimeএবং Time.parseকার্যগুলি সময় অঞ্চল তথ্য ধরে রাখে না। রূপান্তরকালে সমস্ত কিছু স্থানীয় সময় অঞ্চলে রূপান্তরিত হয়। তারিখের গাণিতিকগুলি এখনও কাজ করে তবে আপনি তারিখগুলি তাদের মূল টাইমজোনগুলির সাথে প্রদর্শন করতে পারবেন না। সেই প্রসঙ্গে তথ্য প্রায়শই গুরুত্বপূর্ণ। উদাহরণস্বরূপ, আমি যদি নিউইয়র্কের ব্যবসায়ের সময় সঞ্চালিত লেনদেন দেখতে চাই তবে আমি সম্ভবত তাদের অস্ট্রেলিয়ায় স্থানীয় সময় অঞ্চল নয় (যা নিউইয়র্কের 12 ঘন্টা পূর্বে) নয়, তাদের মূল সময় অঞ্চলগুলিতে প্রদর্শিত দেখতে পছন্দ করি।

নীচের রূপান্তর পদ্ধতিতে tz তথ্য রাখে।

রুবি ১.৮ এর জন্য গর্ডন উইলসনের উত্তরটি দেখুন । এটি ভাল পুরানো নির্ভরযোগ্য রুবি কুকবুক থেকে।

রুবি ১.৯ এর পক্ষে এটি কিছুটা সহজ।

require 'date'

# Create a date in some foreign time zone (middle of the Atlantic)
d = DateTime.new(2010,01,01, 10,00,00, Rational(-2, 24))
puts d

# Convert DateTime to Time, keeping the original timezone
t = Time.new(d.year, d.month, d.day, d.hour, d.min, d.sec, d.zone)
puts t

# Convert Time to DateTime, keeping the original timezone
d = DateTime.new(t.year, t.month, t.day, t.hour, t.min, t.sec, Rational(t.gmt_offset / 3600, 24))
puts d

এটি নিম্নলিখিত মুদ্রণ করে

2010-01-01T10:00:00-02:00
2010-01-01 10:00:00 -0200
2010-01-01T10:00:00-02:00

টাইমজোন সহ পুরো আসল ডেটটাইম তথ্য রাখা আছে।


2
সময় জটিল, তবে বিভিন্ন অন্তর্নির্মিত সময় শ্রেণীর মধ্যে অন্তর্নির্মিত রূপান্তর না দেওয়ার কোনও অজুহাত নেই। আপনি যদি খ্রিস্টপূর্ব 4713 সালে UNIX সময়_টি পাওয়ার চেষ্টা করেন তবে আপনি একটি রেঞ্জএক্সসেপশন নিক্ষেপ করতে পারেন (যদিও একটি বিগনাম নেতিবাচক মানটি আরও ভাল হবে) তবে কমপক্ষে এটির জন্য কোনও পদ্ধতি সরবরাহ করুন।
মার্ক রিড

1
Time#to_datetimeআমার জন্য tz সংরক্ষণ করে দেখা যাচ্ছে:Time.local(0).to_datetime.zone #=> "-07:00"; Time.gm(0).to_datetime.zone #=> "+00:00"
Phrogz

@ ফ্রোগজ ইউটিসি অফসেট সময় অঞ্চল হিসাবে একই জিনিস নয়। একটি ধ্রুবক, অন্যটি দিবালোকের সময় সাশ্রয়ের জন্য বছরের বিভিন্ন সময়ে পরিবর্তন করতে পারে। ডেটটাইমের কোনও জোন নেই, এটি ডিএসটি উপেক্ষা করে। সময় এটিকে সম্মান করে তবে কেবল "স্থানীয়" (সিস্টেম পরিবেশ) টিজেডে।
অ্যান্ড্রু ভিট

1

গর্ডন উইলসন সমাধানের উন্নতি করা, এখানে আমার চেষ্টা:

def to_time
  #Convert a fraction of a day to a number of microseconds
  usec = (sec_fraction * 60 * 60 * 24 * (10**6)).to_i
  t = Time.gm(year, month, day, hour, min, sec, usec)
  t - offset.abs.div(SECONDS_IN_DAY)
end

আপনি টাইমজোনটি হারাতে ইউটিসিতে একই সময় পাবেন (দুর্ভাগ্যক্রমে)

এছাড়াও, আপনার যদি রুবি ১.৯ থাকে তবে কেবল to_timeপদ্ধতিটি ব্যবহার করে দেখুন


0

এ জাতীয় রূপান্তর করার সময় একটিকে অন্য একটি বস্তুতে রূপান্তর করার সময় সময় অঞ্চলগুলির আচরণের বিষয়টি বিবেচনা করা উচিত। আমি এই স্ট্যাকওভারফ্লো পোস্টে কিছু ভাল নোট এবং উদাহরণ পেয়েছি ।

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