-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added separate set of method for java
to improve user experience.
- Loading branch information
1 parent
2f23838
commit 8406f55
Showing
7 changed files
with
263 additions
and
95 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
pubnub-gson/pubnub-gson-api/src/main/java/com/pubnub/api/java/util/TimetokenUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package com.pubnub.api.java.util; | ||
|
||
import java.time.Instant; | ||
|
||
public class TimetokenUtil { | ||
private static final long MINIMAL_TIMETOKEN_VALUE = 10_000_000_000_000_000L; | ||
private static final long MAXIMUM_TIMETOKEN_VALUE = 99_999_999_999_999_999L; | ||
private static final long MINIMAL_UNIX_TIME_VALUE = 1_000_000_000_000L; | ||
private static final long MAXIMUM_UNIX_TIME_VALUE = 9_999_999_999_999L; | ||
private static final int UNIX_TIME_LENGTH_WHEN_IN_MILLISECONDS = 13; | ||
|
||
/** | ||
* Converts a PubNub timetoken (a unique identifier for each message sent and received in a PubNub channel that is | ||
* a number of 100-nanosecond intervals since January 1, 1970) to Instant object representing | ||
* the corresponding date and time. | ||
* | ||
* @param timetoken PubNub timetoken | ||
* @return Instant representing the corresponding date and time. | ||
* @throws IllegalArgumentException if the timetoken does not have 17 digits. | ||
*/ | ||
public static Instant timetokenToInstant(long timetoken) { | ||
if (isLengthDifferentThan17Digits(timetoken)) { | ||
throw new IllegalArgumentException("Timetoken should have 17 digits"); | ||
} | ||
|
||
// Convert timetoken to seconds and nanoseconds components | ||
long epochSeconds = timetoken / 10_000_000; // Divide by 10^7 to get seconds | ||
int epochNanoseconds = (int) ((timetoken % 10_000_000) * 100); // The remainder, multiplied by 100 to get nanoseconds | ||
|
||
return Instant.ofEpochSecond(epochSeconds, epochNanoseconds); | ||
} | ||
|
||
/** | ||
* Converts Instant to a PubNub timetoken. | ||
* | ||
* A PubNub timetoken is a 17-digit number representing the number of 100-nanosecond intervals since January 1, 1970. | ||
* | ||
* @param instant The Instant object to be converted to a PubNub timetoken. | ||
* @return A 17-digit long representing the PubNub timetoken for the given Instant. | ||
*/ | ||
public static long instantToTimetoken(Instant instant) { | ||
long epochSeconds = instant.getEpochSecond(); | ||
int epochNanoseconds = instant.getNano(); | ||
|
||
long pnTimetokenInNanosecondsWithoutNanoPrecision = epochSeconds * 10_000_000; | ||
long nanosecondsForPubNubTimetoken = epochNanoseconds / 100; // PubNub timetoken for nanoseconds store only 7 digits instead of 9 | ||
|
||
return pnTimetokenInNanosecondsWithoutNanoPrecision + nanosecondsForPubNubTimetoken; | ||
} | ||
|
||
/** | ||
* Converts a Unix timestamp (in millis) to a PubNub timetoken. | ||
* | ||
* @param unixTime The Unix timestamp to be converted to a PubNub timetoken. | ||
* @return A 17-digit long representing the PubNub timetoken corresponding to the given Unix timestamp. | ||
* @throws IllegalArgumentException if the unixTime does not have 13 digits. | ||
*/ | ||
public static long unixToTimetoken(long unixTime) { | ||
if (isLengthDifferentThan13Digits(unixTime)) { | ||
throw new IllegalArgumentException("Unix timetoken should have " + UNIX_TIME_LENGTH_WHEN_IN_MILLISECONDS + " digits."); | ||
} | ||
|
||
return unixTime * 10_000; // PubNub timetoken has 17 digits | ||
} | ||
|
||
/** | ||
* Converts a PubNub timetoken to a Unix timestamp (in millis). | ||
* | ||
* A PubNub timetoken is a 17-digit number representing the number of 100-nanosecond intervals since January 1, 1970. | ||
* This function converts the PubNub timetoken to a Unix timestamp by reducing the precision to millis. | ||
* Note that precision finer than millis is lost in this conversion. | ||
* | ||
* @param timetoken The PubNub timetoken to be converted to a Unix timestamp. | ||
* @return A long representing the Unix timestamp in millis corresponding to the given timetoken. | ||
*/ | ||
public static long timetokenToUnix(long timetoken) { | ||
return timetoken / 10_000; // PubNub timetoken has 17 digits | ||
} | ||
|
||
private static boolean isLengthDifferentThan17Digits(long timetoken) { | ||
return timetoken < MINIMAL_TIMETOKEN_VALUE || timetoken > MAXIMUM_TIMETOKEN_VALUE; | ||
} | ||
|
||
private static boolean isLengthDifferentThan13Digits(long unixTime) { | ||
return unixTime < MINIMAL_UNIX_TIME_VALUE || unixTime > MAXIMUM_UNIX_TIME_VALUE; | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
pubnub-gson/pubnub-gson-api/src/test/java/com/pubnub/api/java/util/TimetokenUtilsTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package com.pubnub.api.java.util; | ||
|
||
import org.junit.jupiter.api.Test; | ||
//import com.pubnub.api.utils.TimetokenUtil; | ||
import java.time.Instant; | ||
import java.time.LocalDateTime; | ||
import java.time.ZoneId; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
||
public class TimetokenUtilsTest { | ||
|
||
@Test | ||
public void canConvertTimestampToDateTimeThenFromDateTimeToTimestamp() { | ||
|
||
// given 2024-09-30 11:24:20.623211800 | ||
long timetoken = 17276954606232118L; | ||
|
||
// when | ||
Instant instant = TimetokenUtil.timetokenToInstant(timetoken); | ||
long timetokenResult = TimetokenUtil.instantToTimetoken(instant); | ||
|
||
// then | ||
LocalDateTime localDateTimeInUTC = LocalDateTime.ofInstant(instant, ZoneId.of("UTC")); | ||
assertEquals("2024-09-30", localDateTimeInUTC.toLocalDate().toString()); | ||
assertEquals("11:24:20.623211800", localDateTimeInUTC.toLocalTime().toString()); | ||
assertEquals(timetoken, timetokenResult); | ||
} | ||
|
||
@Test | ||
public void canConvertUnixTimeInMillisecondsToTimetoken() { | ||
// given 2024-10-02 11:02:15.316 | ||
long unixTime = 1727866935316L; | ||
|
||
// when | ||
long timetoken = TimetokenUtil.unixToTimetoken(unixTime); | ||
|
||
// then | ||
Instant instant = TimetokenUtil.timetokenToInstant(timetoken); | ||
LocalDateTime localDateTimeInUTC = LocalDateTime.ofInstant(instant, ZoneId.of("UTC")); | ||
assertEquals("2024-10-02", localDateTimeInUTC.toLocalDate().toString()); | ||
assertEquals("11:02:15.316", localDateTimeInUTC.toLocalTime().toString()); | ||
} | ||
|
||
@Test | ||
public void canConvertUnixTimeNotHaving10Or13Digits() { | ||
long unixTime4Digits = 1_000_000_000L; | ||
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { | ||
TimetokenUtil.unixToTimetoken(unixTime4Digits); | ||
}); | ||
assertEquals("Unix timetoken should have 13 digits.", exception.getMessage()); | ||
} | ||
|
||
@Test | ||
public void canConvertTimestampToUnixTime() { | ||
// given 2024-09-30 11:24:20.623211800 | ||
long timetoken = 17276954606232118L; | ||
|
||
// when | ||
long unixTime = TimetokenUtil.timetokenToUnix(timetoken); | ||
|
||
// then | ||
Instant instant = Instant.ofEpochMilli(unixTime); | ||
LocalDateTime toLocalDateTime = LocalDateTime.ofInstant(instant, ZoneId.of("UTC")); | ||
assertEquals("2024-09-30", toLocalDateTime.toLocalDate().toString()); | ||
assertEquals("11:24:20.623", toLocalDateTime.toLocalTime().toString()); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
pubnub-kotlin/pubnub-kotlin-api/src/commonMain/kotlin/com/pubnub/api/utils/TimetokenUtil.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
package com.pubnub.api.utils | ||
|
||
import kotlinx.datetime.Instant | ||
import kotlin.jvm.JvmStatic | ||
|
||
/** | ||
* Utility object for converting PubNub timetokens to various date-time representations and vice versa. | ||
* | ||
* This utility provides methods for converting between PubNub timetokens, Unix timestamps, and date-time objects. | ||
* A PubNub timetoken is a 17-digit number that represents the number of 100-nanosecond intervals since | ||
* January 1, 1970 (UTC). These methods allow for easy conversion between different time representations | ||
* used in PubNub, Unix, and standard date-time formats. | ||
*/ | ||
class TimetokenUtil { | ||
companion object { | ||
private const val MINIMAL_TIMETOKE_VALUE = 10_000_000_000_000_000 | ||
private const val MAXIMUM_TIMETOKEN_VALUE = 99_999_999_999_999_999 | ||
private const val MINIMAL_UNIX_TIME_VALUE = 1_000_000_000_000 | ||
private const val MAXIMUM_UNIX_TIME_VALUE = 9_999_999_999_999 | ||
private const val UNIX_TIME_LENGHT_WHEN_IN_MILLISECONDS = 13 | ||
|
||
/** | ||
* Converts a PubNub timetoken (a unique identifier for each message sent and received in a PubNub channel that is | ||
* a number of 100-nanosecond intervals since January 1, 1970) to LocalDateTime object representing | ||
* the corresponding date and time. | ||
* | ||
* @param timetoken PubNub timetoken | ||
* @return [Instant] representing the corresponding data and time. | ||
* @throws IllegalArgumentException if the timetoken does not have 17 digits. | ||
*/ | ||
@JvmStatic | ||
fun timetokenToInstant(timetoken: Long): Instant { | ||
if (isLengthDifferentThan17Digits(timetoken)) { | ||
throw IllegalArgumentException("Timetoken should have 17 digits") | ||
} | ||
// Convert timetoken to seconds and nanoseconds components | ||
val epochSeconds = timetoken / 10_000_000 // Divide by 10^7 to get seconds | ||
val epochNanoseconds = | ||
((timetoken % 10_000_000) * 100).toInt() // The remainder, multiplied by 100 to get nanoseconds | ||
|
||
return Instant.fromEpochSeconds(epochSeconds, epochNanoseconds) | ||
} | ||
|
||
/** | ||
* Converts [Instant] to a PubNub timetoken | ||
* | ||
* A PubNub timetoken is a 17-digit number representing the number of 100-nanosecond intervals since January 1, 1970. | ||
* | ||
* @param instant The [Instant] object to be converted to a PubNub timetoken. | ||
* @return A 17-digit [Long] representing the PubNub timetoken for the given [Instant]. | ||
*/ | ||
@JvmStatic | ||
fun instantToTimetoken(instant: Instant): Long { | ||
val epochSeconds: Long = instant.epochSeconds | ||
val epochNanoseconds: Int = instant.nanosecondsOfSecond | ||
|
||
val pnTimetokenInNanosecondsWithoutNanoPrecision = epochSeconds * 10_000_000 | ||
val nanosecondsForPubNubTimetoken = | ||
epochNanoseconds / 100 // PubNub timetoken for nanoseconds store only 7 digits instead of 9 | ||
return pnTimetokenInNanosecondsWithoutNanoPrecision + nanosecondsForPubNubTimetoken | ||
} | ||
|
||
/** | ||
* Converts a Unix timestamp (in millis) to a PubNub timetoken | ||
* | ||
* @param unixTime The Unix timestamp to be converted to a PubNub timetoken. | ||
* @return A 17-digit [Long] representing the PubNub timetoken corresponding to the given Unix timestamp. | ||
* @throws IllegalArgumentException if the unixTime does not have 13 digits. | ||
*/ | ||
@JvmStatic | ||
fun unixToTimetoken(unixTime: Long): Long { | ||
if (isLengthDifferentThan13Digits(unixTime)) { | ||
throw IllegalArgumentException("Unix timetoken should have $UNIX_TIME_LENGHT_WHEN_IN_MILLISECONDS digits.") | ||
} | ||
return unixTime * 10_000 // PubNub timetoken has 17 digits | ||
} | ||
|
||
/** | ||
* Converts a PubNub timetoken to a Unix timestamp (in millis). | ||
* | ||
* A PubNub timetoken is a 17-digit number representing the number of 100-nanosecond intervals since January 1, 1970. | ||
* This function converts the PubNub timetoken to a Unix timestamp by reducing the precision to millis. | ||
* Note that precision finer than millis is lost in this conversion. | ||
* | ||
* @param timetoken The PubNub timetoken to be converted to a Unix timestamp. | ||
* @return A [Long] representing the Unix timestamp in millis corresponding to the given timetoken. | ||
*/ | ||
@JvmStatic | ||
fun timetokenToUnix(timetoken: Long): Long { | ||
return (timetoken / 10_000) // PubNub timetoken has 17 digits | ||
} | ||
|
||
private fun isLengthDifferentThan17Digits(timetoken: Long): Boolean { | ||
return timetoken !in MINIMAL_TIMETOKE_VALUE..MAXIMUM_TIMETOKEN_VALUE | ||
} | ||
|
||
private fun isLengthDifferentThan13Digits(unixTime: Long): Boolean { | ||
return unixTime !in MINIMAL_UNIX_TIME_VALUE..MAXIMUM_UNIX_TIME_VALUE | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
94 changes: 0 additions & 94 deletions
94
...kotlin/pubnub-kotlin-core-api/src/commonMain/kotlin/com/pubnub/api/utils/TimetokenUtil.kt
This file was deleted.
Oops, something went wrong.