Is there a way to determine if a ZonedDateTime (in the past) is in DST or not?
Yes, we've actually made this nice and easy - you just need to call ZonedDateTime.IsDaylightSavingTime. This is implemented by:
Obtaining the ZoneInterval from the time zone at the instant represented by the ZonedDateTime
Obtaining the Savings part of that ZoneInterval
Comparing that with Offset.Zero
Related
Given a table like this:
CREATE TABLE demo (
id BIGINT PRIMARY KEY,
offset_minutes INTEGER NOT NULL,
scheduled_time TIMESTAMP WITH TIME ZONE
);
I want to update scheduled_time to an application-supplied time plus offset_minutes. In plain SQL on PostgreSQL, it'd look something like
UPDATE demo
SET scheduled_time =
timestamp with time zone '2022-09-12T01:23:45Z' +
offset_minutes * interval '1 minute'
WHERE id = 12345;
What's the best way to express this in jOOQ in a database-engine-independent way?
This is the reverse of the usual way people want to add minutes to a time value, which is well-covered by other SO questions: in my case, the Instant is supplied by the code and the number of minutes is in a database column, not the other way around.
The best I've been able to come up with is to do a floating-point calculation on the number of minutes, since we can add days to Instants:
dslContext.update(DEMO)
.set(DEMO.SCHEDULED_TIME,
DSL.instant(instant).add(DEMO.OFFSET_MINUTES.div(24.0 * 60.0)))
.where(DEMO.ID.eq(id))
.execute();
On PostgreSQL, jOOQ ends up generating a SQL expression for the value of the SET clause:
(timestamp with time zone '2022-09-12 01:23:45+00:00' +
("public"."demo"."offset_minutes" / 1.44E3) * interval '1 day')
The fact that jOOQ is generating interval '1 day' makes me hopeful that there's a way to tell it to change day to minute and avoid the floating-point calculation. I'm never nuts about doing floating-point calculations on discrete quantities if it can be avoided.
Pending feature requests
Fixing your immediate problem
There's a pending feature request #6723 to add support for DSL::offsetDateTimeAdd, which would allow for adding intervals to TIMESTAMP WITH TIME ZONE data types.
It still wouldn't work for Instant data types, where we'd need yet another "overload" for all the possible date time arithmetic variants.
Both of these would produce a lot of new methods in an already crowded DSL class, without really adding much new functionality, given they're doing something similar to the existing timestampAdd() or localDateTimeAdd() functions, just offering the same thing for new types.
A more strategic, thorough change
There's a big change #11088 suggested on the long term roadmap, which would allow for more cleanly separating the usual two types T and U involved with a Field:
T being the "JDBC type", i.e. the type the database understands (e.g. OffsetDateTime)
U being the "user type", i.e. the type you want to see in your code (e.g. Instant)
This way, there would be a single method accepting T = OffsetDateTime and any arbitrary U type (e.g. Instant).
Workaround for you right now
While the above tasks take time to get right, you can always use the usual escape hatch and use plain SQL templating. E.g.
DSL.field("({0} + {1} * interval '1 minute')",
SQLDataType.INSTANT,
DSL.instant(instant),
DEMO.OFFSET_MINUTES
);
You can extract the hard-coded arguments (DSL.instant(instant) and DEMO.OFFSET_MINUTES) and make a reusable function for the above, and thus create a mini library for the missing functionality in jOOQ.
Assume we have a value object Duration (with attributes numberOfUnits, unit). Would it be a good idea to treat these objects as equal (for example, overriding Object.equals()) if they have the same duration but different units? Should 1 min be equal to 60 sec.
There are many contradicting examples. With java's BigDecimal compareTo() == 0 does not imply equals() == true (new BigDecimal("0").equals(new BigDecimal("0.0")) returns false). But Duration.ofHours(24).equals(Duration.ofDays(1)) returns true.
That's an unfortunately complicated question.
The simple answer is no: the important goal of value objects is to correctly model queries in your domain.
If it happens that equals in your domain has nice properties, then you should model them and everything is awesome. But if you are modeling something weird then getting it right trumps following the rules everywhere else.
Complications appear when your implementation language introduces contracts for equals that don't match the meaning in your domain. Likely, you will need to invent a different spelling for the domain meaning.
In Java, there are a number of examples where equals doesn't work as you would expect, because the hashCode contract prohibits it.
Well... I upvoted #jonrsharpe comment because without knowing the context it is almost impossible to give you an answer.
An example of what #jonrsharpe means could be that if in your domain you are using Duration VO to compare users input (who choose numberOfUnits and unit in a UI) it is obvious that Duration in minutes is not equal to Duration in seconds even if 1 min = 60 sec because you want to know if the users inputs the same things, and in this case they not.
Now, assuming that you will use Duration just for other things in which the format does not matter and ever means the same thing for domain rules (i.e. outdate something):
Why do you need Duration.unit attribute if it gives you nothing of value in your domain?
Why can not you just work with one unit type internally?
If it is just because different inputs/outputs in your system you should transform it to your internal/external(UI, REST API, etc) representation before apply rules, persist the VO (if needed) and/or showing it in a UI. So, separate input/output concerns from your domain. Maybe Duration (with unit attribue) is not a VO is just part of your ViewModel.
I would like to represent the timestamp coming from an HTMLMediaElement. Its defining characteristics are:
Its value is represented as a Double
It can be queried at any time using getCurrentTime :: IO Double (as partially applied on a given HTMLMediaElement)
It is potentially continuously changing (whenever the media player is playing)
My initial plan was to represent it as a Behavior t Double that re-runs the IO Double every time it is observed, but that hasn't worked out too well.
Things I've tried:
Using a Behavior that is prodded under the hood at a fixed frequency, as described in the workaround section of this question
Passing an Event t () representing the desired sampling frequency, and returning an Event t Double that holds the coinciding timestamps
I don't really like either -- the first one either couples the behaviour (sorry) too much to my specific use case (if I use the eventual sampling frequency I'll use in my app) or seems wasteful (if I use something like 1 kHz sampling when creating the Behavior just to then sample it at 60 Hz on the application end), and the second is quite inflexible if you want to do more than one thing with the timestamp at different sampling rates.
Right now, using an Event to explicitly sample the time (your second option) value is your best bet. We haven't yet created a way to write Behaviors that lazily poll outside resources, although that is something that I hope we'll be able to get done soon.
Keep in mind that, with your second option, you don't necessarily need to use a specific sampling rate; instead, you can sample on-demand, and even have multiple locations doing that sampling. It's not perfect, but I hope that'll let you get the job done!
How do you convert epoch time (unix timestamp) to standard time in D? Is there a way to customize the format?
You really should separate questions out, not ask two completely different questions at the same time.
How do you convert epoch time (unix timestamp) to standard time in D?
If you need to convert from unix time to SysTime's "std time," then you use unixTimeToStdTime:
assert(unixTimeToStdTime(0) == (Date(1970, 1, 1) - Date.init).total!"hnsecs");
So, if you do SysTime(unixTimeToStdTime(0)), you'll get a SysTime in your local time zone at the point in time when it was midnight, January 1st 1970 in UTC (i.e. the epoch time). Unlike the other SysTime constructors, it does not treat the time it's given as being in the timezone that it's given. Rather, it just sets its stdTime to the given value, and it's timezone to the given value. So, to construct an identical SysTime with the other constructors, you'd do something like
auto epochInLocalTime = SysTime(Date(1970, 1, 1), UTC()).toLocalTime();
If you want to convert in the opposite direction, stdTimeToUnixTime will convert a std time to a unix time. However, SysTime has toUnixTime on it, making it so that you generally don't need stdTimeToUnixTime.
time_t epoch = epochInLocalTime.toUnixTime();
However, one thing to be aware of is the fact that std.datetime truly deals with unix time - time_t is always considered to be in UTC. The reason that this matters is that for some inexplicable reason, Windows applies the local time's DST to time_t so that the UTC offset never changes, which means that it's wrong for a good chunk of the year. It works with all of the Microsoft's functions which use time_t, because they expect that nonsense, but you'll have interoperability problems if you try and use a Windows time_t with another box or with a library like std.datetime which actually uses time_t correctly.
Is there a way to customize the format?
You mean that you're looking for a way to provide a user-defined format for a string representing the time (like C's strftime)? std.datetime doesn't have that yet. The API still needs to be designed for it. Some discussion has taken place, but it hasn't been settled on yet. So, it'll happen eventually, but it could be a while.
In the interim, you have toISOString, toISOExtString, and toSimpleString, which use the ISO format, the ISO extended format, and Boost's simple string format respectively. In general, I'd suggest using toISOExtString, because it's both easily read by humans and standard. It's also generally best to put it in UTC (e.g. sysTime.toUTC()) when communicating with other computers (as opposed to printing it out for humans), because then the time zone is part of it, unlike with LocalTime, which doesn't append the time zone.
If you haven't read this article on std.datetime yet, then I suggest that you do, since it should give you a good overview of the module and how to use it.
I'm not familiar with D, but according to std.datetime, you could use these steps
long unixTimeToStdTime(time_t)
struct SysTime(long stdTime)
SysTime.dayOfGregorianCal()
struct Date(int day)
Date.toISOExtString()
I need to name this structure:
struct NameNeeded
{
DateTime timestamp;
float value;
}
I will have arrays of this struct (a time-series).
I'd like a short and suggestive name. The data is financial (and Tick is not a good name).
The best one I can think of is DataPoint, but I feel that a better one exists :)
How would you name it?
Since you have a data value and an associated timestamp, the first thing that popped into my head was DataSample. I pictured a series of these, as if you were taking a digital sampling of an analog signal (the two values were like x- and y-coordinates on a graph).
My old scientist neurons are telling me that this is a Measurement. A measurement is an instrument reading associated with some context - time, position, experimental conditions, and so on.
The other metaphor that springs to mind is a Snapshot, or a moment in an evolving scene illuminated by a strobe light - an Instant, perhaps.
Given that we can't associate a specific concept with the float value structure member, only vague names such as "Value", "Number", "Float" or "Data" come to mind.
The DateTime timestamp member suggests to me that the name should have a time related suffix such as "When", "AtTime", "Instant" or "Moment"
So, combining these name fragments and you could have
ValueWhen
ValueAtInstant
NumberWhen
DataAtTime
etc.
When stuck on a naming problem, consulting a dictionary or thesaurus can sometimes help. It's pleasing to see well chosen type names, and gratifying to come up with them - good luck with your quest.
I would personally include "Float" in the name, to leave open the possibility of providing other time-stamped types. For example, you could provide a timestamped int or enum for analyst recommendation.
If you want the time-stamping to be implicit, consider "FloatValue." Making it implicit might be desirable if other attributes might someday join the timestamp (e.g., source of data, confidence level, or uncertainty).
If you want to be explicit, one possibility would be "RecordedFloat."