• Prime Mover (unregistered)

    900 nanoseconds, not 9,900 nanoseconds, surely?

  • dpm (unregistered) in reply to Prime Mover

    Congratulations on being accepted into the Hobgoblins of Tiny Minds Society.

  • Sauron (unregistered)

    Due to the bad date handling, I'm actually frist.

  • (nodebb)

    I feel like we could get several more WTFs if we asked why these functions are even needed.

  • (nodebb)

    Another WTF is passing the argument by ref and replacing it, instead of returning a new DateTime. DateTime is immutable for good reasons, and making a method that pretends to modify a DateTime (when it actually just replaces the argument's value) is just misleading. Also, without the ref, these methods could have been extension methods, which would be much more convenient to use.

  • Kenji (unregistered)

    The end of yesterday and the end of today are not anchored against the same time- tomorrow, today will "end" a full 9,900 nanoseconds earlier than it did today.

    Yeah, I think there's a mistake. Tomorrow, today will "end" 999.9 Microseconds later than today.

  • Smithers (unregistered) in reply to Prime Mover

    999,900 nanoseconds, not 900 nanoseconds, surely?

  • Sole Purpose Of Visit (unregistered) in reply to dpm

    TO defend Remy against the accusation of being a hobgoblin, I should point out that this is not a foolish consistency -- it is a pointless insistence on exactitude. Pointless partially because (absent either dedicated clocking hardware, or else in the presence of hard real time) a microsecond error here or there is something that is going to happen whether you like it or not.

    Also, there are two separate domains to consider. If you're dealing with (say) banking transactions, you care about ToD (as long as it is consistent within a sensible tolerance). If you work in nanonseconds, or even in microseconds, you probably want dedicated clocking hardware or a hard real time system. In which case you are unlikely to work with ToD (except for display purposes). You are more likely to fire off a timer that counts in nanoseconds (or small multiples thereof), in which case you get what you ask for, and you don't even need to worry about thinks like leap-seconds.

    Let's be honest here. Stipulating that there are 1,000,000,000 bad implementations of a ToD requirement out there ... if you sort them in order of badness, this is probably around the 999,999,900th.

  • SheriffFatman (unregistered) in reply to Prime Mover

    999,900 nanoseconds, I think:

    • 1 millisecond = 1,000 microseconds

    • 1 microsecond = 1,000 nanoseconds

    • therefore 1 millisecond = 1,000,000 nanoseconds

    • therefore 1 millisecond - 100 nanoseconds = 1,000,000 nanoseconds - 100 nanoseconds = 999,900 nanoseconds.

  • (author)

    I'm glad I included the Easy Reader about my need to look up the conversion, because I looked up the conversion and still somehow got the numbers wrong.

  • Debra (unregistered)

    Is the Beatles reference intentional?

  • Mark (unregistered)

    Why has no one pointed out the biggest problem of all: that "ToEndofCurrDay" function only works 363 out of 365 days, because NOT ALL DAYS HAVE 24 HOURS. Thanks to Daylight Saving Time, some days have 23 or 25 hours!

  • Barry Margolin (github) in reply to Sole Purpose Of Visit

    Functions like these are usually used for grouping, so it's important to be consistent. The inconsistency between "end of previous day" and "end of current day" could cause transactions either to be left out of either group or put in both groups.

    The precise millisecond or nanosecond isn't important -- you don't really care of a transaction happened yesterday or today -- but it must only be one or the other.

  • Prime Mover (unregistered) in reply to SheriffFatman

    Yes of course. I forgot there was microseconds in between milliseconds and nanoseconds.

  • Sole Purpose Of Visit (unregistered) in reply to Barry Margolin

    Absolutely true, and that's why you shouldn't mix date-times with ticks. Thus my comment on "two separate domains." (I wasn't very clear there, was I?)

    I imagine you should also use the UTCNow method (or equivalent) to avoid problems with daylight savings and so on, given that the domain in this case is a genuine date-time. It isn't clear from the submission, but I'll lay odds that this is going to be a problem.

    And Remy is quite right -- the inconsistency is annoying. So, yes, it's a WTF, but it's not clear which particular WTF it is.

  • Jonathan (unregistered)

    I know this causes a whole storm of bike shedding disagreements, but isn't this a place where half-open intervals make the problem go away?

  • (nodebb) in reply to Barry Margolin

    Functions like these are usually used for grouping, so it's important to be consistent. The inconsistency between "end of previous day" and "end of current day" could cause transactions either to be left out of either group or put in both groups.

    The precise millisecond or nanosecond isn't important -- you don't really care of a transaction happened yesterday or today -- but it must only be one or the other.

    That was my immediate thought on the end of day functions--you either get duplicates or missing records from a new window.

    I also worry about floating point roundoff with the attempt to get the date only.

  • davethepirate (unregistered)

    Assuming someone used this to query everything that happened before the end of a certain day (not the actual today), if something happened in those last few nanoseconds it would get missed.

  • MaxiTB (unregistered)

    What is up with all those refs? DateTime is a struct for crying out loud, use it that way and return the new value object. And turn this thing into bloody extensions.

  • (nodebb) in reply to Jonathan

    Exactly what I was going to say: half-open intervals. Wouldn't the simplest solution just be (in pseudocode with an abuse of notation) something like:

    start = anchor.truncateToDay() end = start.plusDays(1) interval = [start, end)

    Or even:

    date = anchor.truncateToDay() list.filter(stamp -> stamp.truncateToDay() == date)

    For most business applications, this is what you want. I don't see any reason to infer something like hard-real time requirements from the post, so I don't think we need the complicator's gloves here.

  • (nodebb) in reply to Sole Purpose Of Visit

    What does ToD stand for? I found this page:

    https://acronyms.thefreedictionary.com/TOD

    Some of candidates are Transfer on Death, Tree of Death, Touch of Death, and Trail of Dead, but I wasn't sure and thought you'd clarify it for me.

  • Randal L. Schwartz (google) in reply to Mark

    Thanks to Daylight Saving Time, some days have 23 or 25 hours!

    Or 23.5 hours or 24.5 hours, thanks to some places that shift by a half hour. Yes. DST is a very odd beast, and should be removed everywhere.

  • Fizzlecist (unregistered) in reply to Mark

    To be fair not all countries have daylight savings, and in some countries such as Australia it depends on which state you are as to whether you do or don't have it. That's not to say it isn't a WTF, just a regional one :)

  • DrPepper (unregistered)

    I run into this problem a lot, where a developer confuses one concept (a specific, exact moment in time) and another (a day).

    When UPS says your package is going to arrive on Thursday; they do NOT mean a specific moment on Thursday; and they do not mean exactly at midnight on Thursday. What they mean is "on Thursday".

  • dpm (unregistered) in reply to Mr. TA

    "TOD" in this context means "time of day", i.e. the "HH:MM:SS.nnnnn" portion of a-point-in-time. "Date" is used by normal people to mean a-day-of-the-calendar, but the computer industry uses in to mean that sometimes and a-point-in-time at other times. Just one reason that date/time handling is one of the most frequently hit traps in coding and schema design.

  • The Beast in Black (unregistered) in reply to Mr. TA

    I think it's "Time of Day", but "Touch of Death" applies equally...

  • (nodebb) in reply to dpm

    Thank you. Yes, I'm a naming "nazi", and I am convinced a huge chunk of WTFs in the world (not just software) come from people not being able to communicate clearly.

    With dates and times, I always used "date/time" or "d/t" short version in writing or "DT" in code identifiers for date AND time; "date" for dates; "time" for "time of day"; and "duration" for usage of TimeSpan type .NET for the delta between two d/t or time values (if this makes sense).

    And the critics are going to start explaining how my choice of terms is totally wrong in 3, 2, 1....

  • (nodebb) in reply to The Beast in Black

    Yes, specifically 2 days a year: when DST kicks in and goes back a few months later.

  • Bill T (unregistered) in reply to DrPepper

    Just so - the real WTF IMO is that most language frameworks think that "DateTime at midnight" is the same as Date.

    Java has JodaTime and other libraries (and they threw in Calendar to make date/time handling even more stupid than normal) Javascript has similar libraries. C# finally added DateOnly (!) in .NET 6 (but couldn't bring themselves to call it Date)

    Amazing I'm not bald working with time and date...

  • (nodebb) in reply to Bill T

    They added DateOnly so late because you don't REALLY need it. Sure, it's nice to have DateOnly, but the regular DateTime was perfectly usable, just don't ever touch the time portion - use the y,m,d ctor, and only perform date operations. DateOnly takes 4 bytes instead of 8, and the API surface is "cleaner", but these are really tiny benefits.

  • MaxiTB (unregistered) in reply to Randal L. Schwartz

    It is called using UTC ;-)

  • MaxiTB (unregistered) in reply to Mr. TA

    Actually, it is super meaningless. If you have a local date, it covers 3 days (not just one as a lot expect). So at least the range -1 day to +2 days. Because of time zones. If you include daylight savings it gets even weirder and completely nonlinear and incomplete. Hence you should never use anyhting but UTC for date/time calculations to begin with. Coming back to my previous point, date without time is defined in .net usually als time equals 00:00:00 .. at first glance that seems reasonable but again, it only works for UTC. Every other timezone has historic quirks, heck some timezones havent existed in the past and might not exist in the future, so a notation of +hours is also a poor replacement to guess the proper timezone and therefore allow for calculations.

    Long story short, DateTime are a mess and that should always be in the mind of devs that want to avoid a technical debt hell hole in the future.

    The fillowing rules have served me well after decades of bad experiences:

    • Only use UTC timestames which include date and time.
    • Apply number rules for shortening the time (treat time as similar to the fraction point of a floating number).
    • Use proper conditions for range as in EqualOrBigger plus Smaller (x >= from && x < to) instead of EqualOrSmaller.
    • Always persist UTC timestamps (optional persist a local timestamp plus the timezone preferable one that includes historic data like tz)
    • Always convert date/times to UTC timestamps on your presentation layer; a clean service layer already uses UTC to avoid more translations and validations.

    Now every time again there pops up the example of two New Yorkers going to coffee and NY changing the time zones hence their date changes and yes, that true but it also works the other way around: Because if one of the guys has a meeting before or after this coffee meet up with someone from another time zone, a conflict can occur.

  • (nodebb) in reply to Bill T

    The main reason that Calendar is awful is that the state of calendrical calculations is just plain awful. In particular, you've got the differences between seconds, days and years as base level awfulness, and then you've got politicians messing around with what's effectively timezone definitions on way too frequent a basis.

    Fortunately, in my applications I only really care about simple timestamps and differences between them (in seconds) and can leave the rest of the mess to a rendering problem; I don't have to parse the mess or compute with the horrible bits!

  • (nodebb) in reply to MaxiTB

    I'm confused by your comment. There is no such thing as "local date" - dates don't ever have a timezone concept attached to them. I agree, UTC is the right choice for date/time calculations, but I was talking about why DateOnly wasn't added earlier, and that's for dates, not date/times.

    Then you wrote that one cannot use DateTime with the time portion set to zero, as a date representation, because of UTC and timezones. Huh??? If you don't ever change access the time portion of this DateTime as a date value, why do you even care about the timezone? Why would you need "+hours notation" - what does that even mean?

    Quite the opposite, DateTime is a perfectly usable type, which should be the only type used for storing date/time values. For dates, .NET 6 now has DateOnly, as well - which is basically "half of DateTime". I don't see any issues at all here.

    Prior to DateOnly, DateTime was usable for dates, albeit with the caveat of a) using more RAM than needed, b) having too much API, and c) making it more difficult to read the code, because you had to remember that some DateTime values are date/times and others are dates.

    And your example of a scheduling conflict is exactly the one use case where you do NOT want to store in UTC, and instead want local date/time and timezone ID.

  • nz (unregistered) in reply to WatersOfOblivion
    Comment held for moderation.
  • Gnasher729 (unregistered)
    Comment held for moderation.
  • Matt (unregistered)
    Comment held for moderation.

Leave a comment on “Yesterday and Today”

Log In or post as a guest

Replying to comment #:

« Return to Article