Open daneshk opened 3 months ago
Extracted from the Ballerina time module specification,
A specification of a duration in terms of a variety of units (e.g. months, years) which can be resolved to a definite duration only relative to a particular timestamp.
Apart from seconds, the units are
Note that all of these other than seconds are affected by leap seconds.
If you ignore leap seconds, all except months and years can be resolved into a definite number of seconds independent of a timestamp.
We can represent this as a record with optional fields (or with fields defaulting to 0).
Arithmetic using nominal durations and broken-down date-time has several cases that are poorly defined e.g.
There's an algorithm in XML Schema Part 2 we can use https://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes
In practice, handling leap seconds is often done by relying on systems or services (like NTP servers) that are designed to manage leap seconds. Most applications simply ignore leap seconds because their occurrence is so infrequent and they typically have a negligible impact on most time calculations.
When adding a duration to a specific timestamp while considering Daylight Saving Time (DST), you need to account for potential DST transitions that may cause the local time to shift forward or backward. Here we need timezone-aware timestamps
Using timezone-aware objects (like ZonedDateTime
in Java or datetime with pytz/zoneinfo
in Python) ensures that any DST-related shifts are accurately reflected in the final timestamp.
The proposed design contains APIs to cater to the following scenarios,
Time zone agnostic calculation. The operation is purely mathematical. For example, adding one hour adds one hour to the current time without considering whether that hour crosses a DST boundary.
Time zone aware calculation(Handles Daylight Saving Time (DST)).
The Time duration record definition,
# The time duration record, used to pass the datetime value, needs to be added or subtracted from the civil time.
# Fields can be negative. The negative value will be subtracted from the civil time.
# if any of the three fields are > 0, then all must be >= 0
# if any of the three fields are < 0, then all must be <= 0
type Duration record {|
int years?;
int months?;
int weeks?;
int days?;
int hours?;
int minutes?;
Seconds seconds?;
|};
The module-level method which is time-zone agnostic.
# Adds the given datetime duration to the given civil time. This is a time zone-agnostic calculation
#
# + civil - The civil time to which the duration should be added
# + deltaTime - The time duration to be added
public isolated function civilAddDuration(Civil civil, Duration dateTime) returns Civil;
Sample code:
time:Civil civil = check time:civilFromString("2021-04-12T23:20:50.520Z");
time:Duration duration = {years: 1, months: 2, days: 3, hours: 4, minutes: 5, seconds: 6};
time:Civil newCivil = time:civilAddDuration(civil, duration);
Zone
object like below.public type Zone readonly & object {
# If always at a fixed offset from Utc, then this function returns it; otherwise nil.
#
# + return - The fixed zone offset or nil
public isolated function fixedOffset() returns ZoneOffset?;
# Converts a given `Civil` value to an `Utc` timestamp based on the time zone value.
#
# + civil - `Civil` time
# + return - The corresponding `Utc` value or an error if `civil.timeAbbrev` is missing
public isolated function utcFromCivil(Civil civil) returns Utc|Error;
# Converts a given `Utc` timestamp to a `Civil` value based on the time zone value.
#
# + utc - `Utc` timestamp
# + return - The corresponding `Civil` value
public isolated function utcToCivil(Utc utc) returns Civil;
# Adds the given datetime duration to the given civil time. This is a time zone-aware calculation
# + civil - The civil time to which the duration should be added
# + deltaTime - The datetime duration to be added
public isolated function civilAddDuration(Civil civil, Duration dateTime) returns Civil;
};
Sample code
time:TimeZone timeZone = check new("Asia/Colombo");
time:Civil localTime = check timeZone.utcToCivil(time:utcNow());
time:Duration duration = {years: 1, months: 2, days: 3, hours: 4, minutes: 5, seconds: 6};
time:Civil newCivil = timeZone.civilAddDuration(localTime, duration);
@jclark @sameerajayasoma, could you please review the proposed API to add duration for the civil record? The requirement is to add/subtract a DateTime (provided by the user) from the current date and get the modified date. We only provide the utcAddSeconds
[1] API that works with seconds.
Please assign this issue to me
Can I work on this issue ?
👋 Welcome, @malay5 🚀
We're thrilled to have you join the Ballerina Hacktoberfest community! You have been assigned the issue, and we’re excited to see your contributions.
No contribution is too small, and your feedback is always welcome! Don’t hesitate to ask questions, propose new ideas, or report issues.
Happy coding and welcome aboard! 🎉
Can I work on this issue ?
Thank you, @Atharva1723, for your interest. However, we need to assign @malay5 as she made the request first.
Hi @malay5,
Were you able to work on this issue?
@Danesh Kuruppu please assign issue to me
It seems that @malay5 is unavailable to work on the issue. @Atharva1723, are you available to work on this issue? I appreciate your prompt response so that we can proceed.
@Danesh Kuruppu please assign issue to me
@PentesterPriyanshu Thank you for your interest. If @Atharva1723 is unavailable, we can proceed with you. I appreciate your patience.
Yes I can surely work
Yes I can surely work
Yes I can surely work
Thank you, @Atharva1723. I assigned the issue to you. Please check
I've been meaning to comment on this. One of the design points of the Ballerina time APIs is that they handle leap seconds properly. Although they are an immense pain in the neck, they are a fact of life.
You can handle them properly with the Duration type. The key point is that not all minutes have 60 seconds. The last minute of UTC days where a leap second happens have 59 or 60 seconds. We can normalize Durations into a combination of seconds, minutes and months.
When you specify a duration as a number of minutes, then it effectively ignores leap seconds, and you can do the computation without knowing when there were leap seconds (this is usually what people want).
It's a matter of people saying what they want. Imagine a duration of 86401 seconds. You need to decide whether you always want an elapsed time of 86401 seconds (even in the presence of a a leap second), in which case you would specify a duration of 86401 seconds, or whether you really mean 24 hours plus 1 second, in which case you would have a normalized duration of 1440 minutes and 1 second, which might have an elapsed time of 86399 or 88401 seconds in rare circumstances.
This means that in some cases the addition/subtraction of a duration will need to know about leap seconds, and it may fail if the duration is past the last known leap second. There should be an object like a time zone that includes this information, and there should be addition/subtraction methods that return an error in the case where they need leap second information that is not available.
We should be implementing time APIs using as much Ballerina as possible, rather than just a thin layer on top of Java APIs. WSO2 won't be using Java for ever.
@Atharva1723, Based on @jclark's comment, we need to incorporate the leap seconds into the original design as well. Are you still active on this issue?
Yes working on the issue
Great. Thanks, @Atharva1723. To capture the leap seconds, we need to change our original design. Let's work together. Please keep us updated on the progress
@Atharva1723,
Given the complexity involved in incorporating leap seconds into the design, we believe it is challenging for external users to contribute effectively to this issue. Therefore, we have decided to remove this issue from Hacktoberfest and continue working on it within our internal team.
Could you please update me on your current progress so that we can evaluate it and determine the next steps?
I apologize for retracting this issue, and I appreciate your interest and contributions. Thank you!
Description: In the current time module, we only support adding/subtracting seconds from the given time in UTC. This is because we don't support advanced cases like leap seconds, daylight saving, etc in the module. If we need to support adding/subtracting specific no of year, month, and date, we need to consider those scenarios as well.
This task is to check the possibility of supporting it in the time module.
Refer: https://github.com/wso2-enterprise/internal-support-ballerina/issues/743