|
32 | 32 | import java.nio.charset.CharsetEncoder;
|
33 | 33 | import java.nio.charset.CoderResult;
|
34 | 34 | import java.nio.charset.CodingErrorAction;
|
| 35 | +import java.time.Instant; |
35 | 36 |
|
36 | 37 | import static org.msgpack.core.MessagePack.Code.ARRAY16;
|
37 | 38 | import static org.msgpack.core.MessagePack.Code.ARRAY32;
|
|
41 | 42 | import static org.msgpack.core.MessagePack.Code.EXT16;
|
42 | 43 | import static org.msgpack.core.MessagePack.Code.EXT32;
|
43 | 44 | import static org.msgpack.core.MessagePack.Code.EXT8;
|
| 45 | +import static org.msgpack.core.MessagePack.Code.EXT_TIMESTAMP; |
44 | 46 | import static org.msgpack.core.MessagePack.Code.FALSE;
|
45 | 47 | import static org.msgpack.core.MessagePack.Code.FIXARRAY_PREFIX;
|
46 | 48 | import static org.msgpack.core.MessagePack.Code.FIXEXT1;
|
@@ -798,6 +800,111 @@ else if (s.length() < (1 << 16)) {
|
798 | 800 | return this;
|
799 | 801 | }
|
800 | 802 |
|
| 803 | + /** |
| 804 | + * Writes a Timestamp value. |
| 805 | + * |
| 806 | + * <p> |
| 807 | + * This method writes a timestamp value using timestamp format family. |
| 808 | + * |
| 809 | + * @param instant the timestamp to be written |
| 810 | + * @return this packer |
| 811 | + * @throws IOException when underlying output throws IOException |
| 812 | + */ |
| 813 | + public MessagePacker packTimestamp(Instant instant) |
| 814 | + throws IOException |
| 815 | + { |
| 816 | + return packTimestamp(instant.getEpochSecond(), instant.getNano()); |
| 817 | + } |
| 818 | + |
| 819 | + /** |
| 820 | + * Writes a Timesamp value using a millisecond value (e.g., System.currentTimeMillis()) |
| 821 | + * @param millis the millisecond value |
| 822 | + * @return this packer |
| 823 | + * @throws IOException when underlying output throws IOException |
| 824 | + */ |
| 825 | + public MessagePacker packTimestamp(long millis) |
| 826 | + throws IOException |
| 827 | + { |
| 828 | + return packTimestamp(Instant.ofEpochMilli(millis)); |
| 829 | + } |
| 830 | + |
| 831 | + private static final long NANOS_PER_SECOND = 1000000000L; |
| 832 | + |
| 833 | + /** |
| 834 | + * Writes a Timestamp value. |
| 835 | + * |
| 836 | + * <p> |
| 837 | + * This method writes a timestamp value using timestamp format family. |
| 838 | + * |
| 839 | + * @param epochSecond the number of seconds from 1970-01-01T00:00:00Z |
| 840 | + * @param nanoAdjustment the nanosecond adjustment to the number of seconds, positive or negative |
| 841 | + * @return this |
| 842 | + * @throws IOException when underlying output throws IOException |
| 843 | + * @throws ArithmeticException when epochSecond plus nanoAdjustment in seconds exceeds the range of long |
| 844 | + */ |
| 845 | + public MessagePacker packTimestamp(long epochSecond, int nanoAdjustment) |
| 846 | + throws IOException, ArithmeticException |
| 847 | + { |
| 848 | + long sec = Math.addExact(epochSecond, Math.floorDiv(nanoAdjustment, NANOS_PER_SECOND)); |
| 849 | + long nsec = Math.floorMod((long) nanoAdjustment, NANOS_PER_SECOND); |
| 850 | + |
| 851 | + if (sec >>> 34 == 0) { |
| 852 | + // sec can be serialized in 34 bits. |
| 853 | + long data64 = (nsec << 34) | sec; |
| 854 | + if ((data64 & 0xffffffff00000000L) == 0L) { |
| 855 | + // sec can be serialized in 32 bits and nsec is 0. |
| 856 | + // use timestamp 32 |
| 857 | + writeTimestamp32((int) sec); |
| 858 | + } |
| 859 | + else { |
| 860 | + // sec exceeded 32 bits or nsec is not 0. |
| 861 | + // use timestamp 64 |
| 862 | + writeTimestamp64(data64); |
| 863 | + } |
| 864 | + } |
| 865 | + else { |
| 866 | + // use timestamp 96 format |
| 867 | + writeTimestamp96(sec, (int) nsec); |
| 868 | + } |
| 869 | + return this; |
| 870 | + } |
| 871 | + |
| 872 | + private void writeTimestamp32(int sec) |
| 873 | + throws IOException |
| 874 | + { |
| 875 | + // timestamp 32 in fixext 4 |
| 876 | + ensureCapacity(6); |
| 877 | + buffer.putByte(position++, FIXEXT4); |
| 878 | + buffer.putByte(position++, EXT_TIMESTAMP); |
| 879 | + buffer.putInt(position, sec); |
| 880 | + position += 4; |
| 881 | + } |
| 882 | + |
| 883 | + private void writeTimestamp64(long data64) |
| 884 | + throws IOException |
| 885 | + { |
| 886 | + // timestamp 64 in fixext 8 |
| 887 | + ensureCapacity(10); |
| 888 | + buffer.putByte(position++, FIXEXT8); |
| 889 | + buffer.putByte(position++, EXT_TIMESTAMP); |
| 890 | + buffer.putLong(position, data64); |
| 891 | + position += 8; |
| 892 | + } |
| 893 | + |
| 894 | + private void writeTimestamp96(long sec, int nsec) |
| 895 | + throws IOException |
| 896 | + { |
| 897 | + // timestamp 96 in ext 8 |
| 898 | + ensureCapacity(15); |
| 899 | + buffer.putByte(position++, EXT8); |
| 900 | + buffer.putByte(position++, (byte) 12); // length of nsec and sec |
| 901 | + buffer.putByte(position++, EXT_TIMESTAMP); |
| 902 | + buffer.putInt(position, nsec); |
| 903 | + position += 4; |
| 904 | + buffer.putLong(position, sec); |
| 905 | + position += 8; |
| 906 | + } |
| 907 | + |
801 | 908 | /**
|
802 | 909 | * Writes header of an Array value.
|
803 | 910 | * <p>
|
|
0 commit comments