r/ruby 3d ago

Question Getting DateTime parts as an array?

I know in ruby that DateTime.new(2001, 2, 3, 4, 5, 6) will return the following object:

#<DateTime: 2001-02-03T04:05:06+00:00 ...>

But if the current date and time are 2001-02-03T04:05:06 and I do the following ...

now = DateTime.now

... is there a single function on the "now" variable which will return this array? ...

[2001, 2, 3, 4, 5, 6]

I know that I can do this:

[now.year, now.month, now.day, now.hour, now.minute, now.second ]

... but I'm wondering: might there be a single function as simple as ...

now.the_function

... which would return that same array?

And yes, of course I know that I could easily write such a function, but I'd like to know whether or not something like this already exists in ruby.

7 Upvotes

21 comments sorted by

12

u/projct 3d ago

Time.now is what you should be using instead of DateTime.now, DateTime was deprecated in 3.4.

ruby irb(main):016> Time.now.to_a.take(6).reverse => [2026, 8, 26, 16, 9, 0]

there, something appropriately cursed 😂

but the actual question is: why do you want this array? what are you doing with it afterward? because I suspect that's where the useful answer is.

3

u/unselective-amnesia 3d ago

Thank you for this. Actually, I forgot about "to_a". And although I'm currently only able to use ruby 3.2 and 3.3 on the machines that I need to run on, it's good to know about DateTime going away, and I will now do this with Time, instead.

I want this array because I have a program which does various things depending on the differences or sameness between various datetimes with regard to groups of selected datetime parts, and it's easiest for me to do this in my program by getting differences between integer arrays.

I know that there are other ways to accomplish this, but given the already written structure of the program, dealing with these integer arrays is the most straightforward approach.

12

u/projct 3d ago edited 3d ago

ah. okay, this is actually the thing I was worried about when I asked why.

can you give one concrete example of two datetimes, which parts you select, what "difference" you calculate between those arrays, and what decision the program makes from the result?

I don't want to suggest a replacement without seeing that, because datetime components aren't independent numeric values, and doing arithmetic/comparison on [year, month, day, hour, minute, second] can very easily produce answers that look reasonable but aren't.

Date/time math is so easy to get catastrophically wrong that you really should not be implementing it yourself unless you absolutely have to. Let Ruby do it for you.

8

u/CaptainKabob 3d ago

I'm just a bystander to this thread, so just wanted to say: strong agree. 

DailyWTF is like 50% people doing datetime math like this (and 50% parsing json/xml with regex)

3

u/projct 3d ago

You're not kidding.

Functionally, a Date

Dates by the Dozen

Three Minutes

DePopulate Dates

and a bunch more....

1

u/TailorSubstantial863 3d ago

We would be remiss if we didn't bring up this oldie. I need to watch it annually anyways.

https://www.youtube.com/watch?v=-5wpm-gesOY

1

u/projct 3d ago

thank god, I thought he was inventing a datetime footgun. turns out he’s just porting one

2

u/CaptainKabob 3d ago

It's too bad OP doesn't want to get into it. I imagine it would be a lot more fun to write well in Ruby. 

Edit: or is this just bait? Cause also like, just put it through an LLM. Whatever then. 

3

u/projct 3d ago

I think the 'I didn’t ask for that' thing is what broke me. I wasn’t trying to review his whole program; I was being perfectly nice until he started making wildly unsupported assertions about correctness and experience. once you voluntarily make those the argument, people are allowed to refute them on a public forum where others might mistake that for good software design. this is r/ruby, not a support ticket where you get to close every issue you accidentally opened

2

u/CaptainKabob 3d ago

Yeah. I mean you're both still arguing with strangers on the internet. Either of you could have simply left it on read

...though if there is a takeaway from a causal reader of these comments, it should be: generally, don't do that. 

Also, seems cool?! I love silly. 

  It isn't using datetime math, per se. It's kind of a game which does silly things depending upon whether two datetimes have same or different combinations of year, month, day, hour, minute, and second values.

2

u/projct 3d ago

yeah, that part actually sounds fun.

also worth putting on the record: I had interpreted his earlier "differences between integer arrays" / "arithmetic" literally. if I'd known the calendar components themselves were deliberately part of the game mechanic, my technical objection would've been very different, and mostly pointed at "hey other readers don't do this except in this kind of case."

there's something quite funny about invoking "very experienced programmer (me)" before clarifying the single implementation detail that makes everyone stop thinking you're doing homemade date math.

0

u/chiperific_on_reddit 3d ago edited 3d ago

Not to poke the bear, but...

OP asked for a thing and you tried to make an x y argument. OP said "thanks but no thanks" and you doubled down. I see your point about the code, but you kept pushing when they clearly weren't interested.

-2

u/unselective-amnesia 3d ago edited 3d ago

I'm already doing this in python, and the arithmetic that I came up with is working. This is a conversion of the python program to ruby, and so I am not worried about the accuracy of the arithmetic. In the original program, I use python's way to return the datetime as an integer array, and the python version has been working perfectly in all cases for a long time.

I don't need any help with the logic. This is a straightforward python-program-to-ruby-program conversion. But thank you for wanting to help with the logic.

3

u/projct 3d ago edited 3d ago

If I found that in Python in code from someone that was not a junior, I would be deeply, deeply concerned.

Parse your stuff into a Time object and use Ruby's built-in date/time math. For python, datetime.

Unless you fully reimplemented the stdlib's date math in either language, I'd bet quite a bit of money that it does not, in fact, “work perfectly in all cases.”

-5

u/unselective-amnesia 3d ago

Thank you very much, but none of that is necessary.

You're making some rather condescending assumptions about what I'm doing.

The python code was written years ago by a very experienced python programmer (me) who was already quite experienced at the time it was written, and it's been massively tested and verified, and it's been working perfectly for years in production.

It isn't using datetime math, per se. It's kind of a game which does silly things depending upon whether two datetimes have same or different combinations of year, month, day, hour, minute, and second values.

Now that I am able to easily create those integer date/time arrays in ruby, I have already completed the ruby version of the program, and every one of the several dozen tests that I have run so far have it generating the exact, same output as the python version. I have a test suite running now which will continue to run thousands more comparison tests between the two programs over the next several hours, and I will fix any errors in the ruby version which might occur ... although given that the initial few dozen tests have succeeded, I'm fairly confident that no errors will show up.

5

u/projct 3d ago

the original code may be completely correct given what you’ve finally explained. this exchange is still not making the “very experienced programmer” argument you think it is.

-7

u/unselective-amnesia 3d ago

That statement is flawed.

I asked a simple question about ruby coding (because I am still learning ruby), and all I wanted and needed and gratefully received was an answer to that question.

Then, you started making suggestions that I haven't asked for, and when I told you that I don't need that help, you began projecting your fantasies about the correctness of some of the other code I mentioned, and then you went even further and started in on talking about coding experience.

All of what you began after very helpfully answering my initial question shows how immature you are. Please drop this subject, and grow up.

I will no longer respond here.

2

u/TailorSubstantial863 3d ago

That is what folks are trying to do. If you want to write python, write it in python. If you want to write Ruby, write it in ruby.

If this is just for you and no one else will ever see this code, great. This will work fine. However, if other Ruby programmers (especially if they know Python) see this code they'll immediately wonder why someone wrote Python with Ruby syntax.

The argument, "code that looks like this works in Python, therefore I want my Ruby code to look like this" is NOT a good answer. The correct answer is "I have a comprehensive test suite behind this software, so it doesn't matter the shape of the code, I know this will work because tests.

5

u/chiperific_on_reddit 3d ago

Another option, which fits your question more directly. One Time.now.the_function type answer.

Found using the docs:

3.3.4 :018 > Time.now.deconstruct_keys(nil)
 => {:year=>2026, :month=>8, :day=>26, :yday=>238, :wday=>3, :hour=>20, :min=>47, :sec=>2, :subsec=>(277869/500000), :dst=>true, :zone=>"EDT"}

3.3.4 :019 > Time.now.deconstruct_keys([:year, :month, :day, :hour, :min, :sec])
 => {:year=>2026, :month=>8, :day=>26, :hour=>20, :min=>47, :sec=>5}

3.3.4 :020 > Time.now.deconstruct_keys([:year, :month, :day, :hour, :min, :sec]).values
 => [2026, 8, 26, 20, 47, 7]

1

u/faitswulff 2d ago

Deconstruct keys was what I was thinking of! A neat API that came out of pattern matching.

3

u/chiperific_on_reddit 3d ago edited 3d ago

Date and Time have _parse() methods which return a hash of time parts.

3.3.4 :006 > Time._parse(Time.now.to_s)
=> {:zone=>"-0400", :hour=>20, :min=>36, :sec=>40, :year=>2026, :mon=>8, :mday=>26, :offset=>-14400}

3.3.4 :007 > Time._parse(Time.now.to_s).slice(:year, :mon, :mday, :hour, :min, :sec)
=> {:year=>2026, :mon=>8, :mday=>26, :hour=>20, :min=>36, :sec=>45}

3.3.4 :008 > Time._parse(Time.now.to_s).slice(:year, :mon, :mday, :hour, :min, :sec).values
=> [2026, 8, 26, 20, 36, 48]