@@ -11,8 +11,24 @@ namespace SciSharp.MySQL.Replication.Types
1111 /// <remarks>
1212 /// Handles the reading and conversion of MySQL TIMESTAMP values with fractional seconds.
1313 /// </remarks>
14- class TimestampV2Type : TimeBaseType , IMySQLDataType
14+ class TimestampV2Type : TimeBaseType , IMySQLDataType , IColumnMetadataLoader
1515 {
16+ // Unix epoch start for MySQL TIMESTAMP (1970-01-01 00:00:00 UTC)
17+ private static readonly DateTime UnixEpoch = new DateTime ( 1970 , 1 , 1 , 0 , 0 , 0 , DateTimeKind . Utc ) ;
18+
19+ /// <summary>
20+ /// Loads metadata for TIMESTAMP2 type.
21+ /// </summary>
22+ /// <param name="columnMetadata">The column metadata object.</param>
23+ public void LoadMetadataValue ( ColumnMetadata columnMetadata )
24+ {
25+ // For TIMESTAMP2, the metadata value represents the fractional seconds precision (0-6)
26+ columnMetadata . Options = new TimestampV2Options
27+ {
28+ FractionalSecondsPrecision = columnMetadata . MetadataValue [ 0 ]
29+ } ;
30+ }
31+
1632 /// <summary>
1733 /// Reads a TIMESTAMP2 value from the binary log.
1834 /// </summary>
@@ -21,11 +37,56 @@ class TimestampV2Type : TimeBaseType, IMySQLDataType
2137 /// <returns>A DateTime object representing the MySQL TIMESTAMP2 value.</returns>
2238 public object ReadValue ( ref SequenceReader < byte > reader , ColumnMetadata columnMetadata )
2339 {
24- int meta = columnMetadata . MetadataValue [ 0 ] ;
25- var millis = ( long ) reader . ReadBigEndianInteger ( 4 ) ;
26- var fsp = ReadFractionalSeconds ( ref reader , meta ) ;
27- var ticks = millis * 1000 + fsp / 1000 ;
28- return new DateTime ( ticks ) ;
40+ // Get the precision from metadata
41+ int fsp = columnMetadata . Options is TimestampV2Options options ?
42+ options . FractionalSecondsPrecision : 0 ;
43+
44+ // Read the 4-byte seconds part (big-endian integer representing seconds since Unix epoch)
45+ byte b0 , b1 , b2 , b3 ;
46+ reader . TryRead ( out b0 ) ;
47+ reader . TryRead ( out b1 ) ;
48+ reader . TryRead ( out b2 ) ;
49+ reader . TryRead ( out b3 ) ;
50+
51+ uint secondsSinceEpoch = ( ( uint ) b0 << 24 ) | ( ( uint ) b1 << 16 ) | ( ( uint ) b2 << 8 ) | b3 ;
52+
53+ // Start with the base DateTime (seconds part)
54+ DateTime timestamp = UnixEpoch . AddSeconds ( secondsSinceEpoch ) ;
55+
56+ // Read fractional seconds if precision > 0
57+ if ( fsp > 0 )
58+ {
59+ int fractionalValue = ReadFractionalSeconds ( ref reader , fsp ) ;
60+
61+ // Calculate microseconds
62+ int microseconds = 0 ;
63+ switch ( fsp )
64+ {
65+ case 1 : microseconds = fractionalValue * 100000 ; break ;
66+ case 2 : microseconds = fractionalValue * 10000 ; break ;
67+ case 3 : microseconds = fractionalValue * 1000 ; break ;
68+ case 4 : microseconds = fractionalValue * 100 ; break ;
69+ case 5 : microseconds = fractionalValue * 10 ; break ;
70+ case 6 : microseconds = fractionalValue ; break ;
71+ }
72+
73+ // Add microsecond precision to the DateTime
74+ // 1 tick = 100 nanoseconds, 1 microsecond = 10 ticks
75+ timestamp = timestamp . AddTicks ( microseconds * 10 ) ;
76+ }
77+
78+ return timestamp ;
2979 }
3080 }
81+
82+ /// <summary>
83+ /// Options specific to TIMESTAMP2 data type.
84+ /// </summary>
85+ class TimestampV2Options
86+ {
87+ /// <summary>
88+ /// Gets or sets the precision of fractional seconds (0-6).
89+ /// </summary>
90+ public int FractionalSecondsPrecision { get ; set ; }
91+ }
3192}
0 commit comments