Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to convert time:Civil to string by using the time abbreviation #487

Merged
merged 14 commits into from
Sep 12, 2024
6 changes: 3 additions & 3 deletions ballerina/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
org = "ballerina"
name = "time"
version = "2.4.0"
version = "2.5.0"
authors = ["Ballerina"]
keywords = ["time", "utc", "epoch", "civil"]
repository = "https://github.com/ballerina-platform/module-ballerina-time"
Expand All @@ -15,5 +15,5 @@ graalvmCompatible = true
[[platform.java17.dependency]]
groupId = "io.ballerina.stdlib"
artifactId = "time-native"
version = "2.4.0"
path = "../native/build/libs/time-native-2.4.0.jar"
version = "2.5.0"
path = "../native/build/libs/time-native-2.5.0-SNAPSHOT.jar"
2 changes: 1 addition & 1 deletion ballerina/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ modules = [
[[package]]
org = "ballerina"
name = "time"
version = "2.4.0"
version = "2.5.0"
dependencies = [
{org = "ballerina", name = "jballerina.java"},
{org = "ballerina", name = "test"}
Expand Down
35 changes: 8 additions & 27 deletions ballerina/tests/time_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ isolated function testCivilToString() returns Error? {
utcOffset: zoneOffset
};
string civilStr = check civilToString(civil);
string expectedStr = "2021-03-04T19:03:28.839564Z";
string expectedStr = "2021-03-05T00:33:28.839564+05:30";
test:assertEquals(civilStr, expectedStr);
}

Expand All @@ -383,23 +383,23 @@ isolated function testCivilToStringWithTimeOfDay() returns Error? {
utcOffset: zoneOffset
};
string civilStr = check civilToString(civil);
string expectedStr = "2021-03-04T19:03:28.839564Z";
string expectedStr = "2021-03-05T00:33:28.839564+05:30";
test:assertEquals(civilStr, expectedStr);
}

@test:Config {}
isolated function testCivilToStringWithoutOffset() {
isolated function testCivilToStringWithTimeAbbreviation() returns Error? {
Civil civil = {
year: 2021,
month: 4,
day: 13,
hour: 4,
minute: 70,
minute: 33,
timeAbbrev: "Asia/Colombo"
};
string|Error err = civilToString(civil);
test:assertTrue(err is Error);
test:assertEquals((<Error>err).message(), "civil.utcOffset must not be null");
string civilStr = check civilToString(civil);
string expectedStr = "2021-04-13T04:33+05:30[Asia/Colombo]";
test:assertEquals(civilStr, expectedStr);
}

@test:Config {}
Expand Down Expand Up @@ -727,25 +727,6 @@ isolated function testUtcFromCivilWithEmptyTimeOffsetNegative() returns Error? {
}
}

@test:Config {enable: true}
isolated function testCivilToStringWithEmptyTimeOffsetNegative() returns Error? {
Civil civil = {
year: 2021,
month: 4,
day: 12,
hour: 23,
minute: 20,
second: 50.52,
timeAbbrev: "Asia/Colombo"
};
string|error civilString = civilToString(civil);
if civilString is error {
test:assertEquals(civilString.message(), "civil.utcOffset must not be null");
} else {
test:assertFail("civilString should be error");
}
}

isolated function testUtcFromCivilWithEmptyTimeOffsetAndAbbreviation() returns Error? {
Utc expectedUtc = check utcFromString("2021-04-12T23:20:50.520Z");
Civil civil = {
Expand Down Expand Up @@ -776,7 +757,7 @@ isolated function testCivilToStringWithEmptyTimeOffsetAndAbbreviation() returns
};
string|error civilString = civilToString(civil);
if civilString is error {
test:assertEquals(civilString.message(), "civil.utcOffset must not be null");
test:assertEquals(civilString.message(), "civil.utcOffset and civil.timeAbbrev both must not be null");
} else {
test:assertFail("civilString should be error");
}
Expand Down
39 changes: 21 additions & 18 deletions ballerina/time_apis.bal
Original file line number Diff line number Diff line change
Expand Up @@ -162,31 +162,33 @@ public isolated function civilFromString(string dateTimeString) returns Civil|Er
return check externCivilFromString(dateTimeString);
}

# Obtain a RFC 3339 timestamp (e.g., `2007-12-03T10:15:30.00Z`) from a given `time:Civil`.
# Obtain a RFC 3339 timestamp (e.g., `2021-03-05T00:33:28.839564+05:30`) from a given `time:Civil`.
# ```ballerina
# time:Civil civil = check time:civilFromString("2007-12-03T10:15:30.00Z");
# string|time:Error civilString = time:civilToString(civil);
# ```
# + civil - `time:Civil` that needs to be converted
# + return - The corresponding string value or an error if the specified `time:Civil` contains invalid parameters (e.g., `month` > 12)
public isolated function civilToString(Civil civil) returns string|Error {
ZoneOffset utcOffset;
if civil?.utcOffset is () {
if civil?.timeAbbrev !is () && string:toLowerAscii(<string>civil?.timeAbbrev) == "z" {
utcOffset = <ZoneOffset>{hours: 0, minutes: 0, seconds: 0};
} else {
return error FormatError("civil.utcOffset must not be null");
}
} else {
utcOffset = <ZoneOffset>civil?.utcOffset;
ZoneOffset? utcOffset = civil?.utcOffset;
string? timeAbbrev = civil?.timeAbbrev;

HeaderZoneHandling zoneHandling = PREFER_ZONE_OFFSET;
if utcOffset is () && timeAbbrev is () {
return error FormatError("civil.utcOffset and civil.timeAbbrev both must not be null");
ayeshLK marked this conversation as resolved.
Show resolved Hide resolved
} else if utcOffset is ZoneOffset {
utcOffset = <ZoneOffset>utcOffset;
} else if timeAbbrev is string {
zoneHandling = PREFER_TIME_ABBREV;
}
decimal? civilTimeSecField = civil?.second;
decimal? utcOffsetSecField = utcOffset?.seconds;
decimal civilTimeSeconds = (civilTimeSecField is Seconds) ? civilTimeSecField : 0.0;
decimal utcOffsetSeconds = (utcOffsetSecField is decimal) ? utcOffsetSecField : 0.0;

return externCivilToString(civil.year, civil.month, civil.day, civil.hour, civil.minute, civilTimeSeconds, utcOffset.
hours, utcOffset.minutes, utcOffsetSeconds);
int utcOffsetHours = utcOffset?.hours ?: 0;
int utcOffsetMinutes = utcOffset?.minutes ?: 0;
decimal utcOffsetSeconds = utcOffset?.seconds ?: 0.0;
decimal civilTimeSeconds = civil?.second ?: 0.0;

return externCivilToString(civil.year, civil.month, civil.day, civil.hour, civil.minute, civilTimeSeconds,
utcOffsetHours, utcOffsetMinutes, utcOffsetSeconds, timeAbbrev ?: "", zoneHandling);
}

# Converts a given UTC to an email formatted string (e.g `Mon, 3 Dec 2007 10:15:30 GMT`).
Expand Down Expand Up @@ -298,8 +300,9 @@ isolated function externCivilFromString(string dateTimeString) returns Civil|Err
'class: "io.ballerina.stdlib.time.nativeimpl.ExternMethods"
} external;

isolated function externCivilToString(int year, int month, int day, int hour, int minute, decimal second, int zoneHour,
int zoneMinute, decimal zoneSecond) returns string|Error = @java:Method {
isolated function externCivilToString(int year, int month, int day, int hour, int minute, decimal second,
int zoneHour, int zoneMinute, decimal zoneSecond,
string timeAbber, HeaderZoneHandling zoneHandling) returns string|Error = @java:Method {
name: "externCivilToString",
'class: "io.ballerina.stdlib.time.nativeimpl.ExternMethods"
} external;
Expand Down
5 changes: 5 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [unreleased]

### Fixed
- [When converting a `time:Civil` with time-zone information to a string using `time:civilToString` API error is thrown](https://github.com/ballerina-platform/ballerina-library/issues/6986)

## [2.3.0] - 2023-06-30
### changed
- [Mark Standard Libraries as GraalVM Compatible](https://github.com/ballerina-platform/ballerina-standard-library/issues/4568)
- [Add support for inferring utc offset for zulu time(Z) in utcFromCivil and civilToString APIs](https://github.com/ballerina-platform/module-ballerina-time/pull/459)
Expand Down
2 changes: 1 addition & 1 deletion docs/spec/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ The time library contains several conversion APIs to convert UTC to civil. The t
```ballerina
public isolated function civilFromString(string dateTimeString) returns Civil|Error;
```
4. Civil to an RFC timestamp string
4. Civil to an RFC 3339 timestamp string (e.g., `2021-03-05T00:33:28.839564+05:30`).
```ballerina
public isolated function civilToString(Civil civil) returns string|Error;
```
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
org.gradle.caching=true
group=io.ballerina.stdlib
version=2.4.1-SNAPSHOT
version=2.5.0-SNAPSHOT
ballerinaLangVersion=2201.8.0
puppycrawlCheckstyleVersion=10.12.0
ballerinaGradlePluginVersion=2.0.1
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,13 @@ public static Object externCivilFromEmailString(BString dateTimeString) {
}

public static Object externCivilToString(long year, long month, long day, long hour, long minute, BDecimal second,
long zoneHour, long zoneMinute, BDecimal zoneSecond) {
long zoneHour, long zoneMinute, BDecimal zoneSecond, BString zoneAbbr,
BString zoneHandling) {

try {
ZonedDateTime dateTime = TimeValueHandler.createZoneDateTimeFromCivilValues(year, month, day, hour,
minute, second, zoneHour, zoneMinute, zoneSecond, null,
Constants.HeaderZoneHandling.PREFER_ZONE_OFFSET.toString());
return StringUtils.fromString(dateTime.toInstant().toString());
minute, second, zoneHour, zoneMinute, zoneSecond, zoneAbbr, zoneHandling.getValue());
return StringUtils.fromString(dateTime.toString());
} catch (DateTimeException e) {
return Utils.createError(Errors.FormatError, e.getMessage());
}
Expand Down
Loading