Skip to content

fix: handle IB formatted timestamps and optional realtime integer fields#443

Merged
wboayue merged 6 commits intowboayue:mainfrom
faysou:improvements
Apr 9, 2026
Merged

fix: handle IB formatted timestamps and optional realtime integer fields#443
wboayue merged 6 commits intowboayue:mainfrom
faysou:improvements

Conversation

@faysou
Copy link
Copy Markdown
Contributor

@faysou faysou commented Mar 29, 2026

Summary

  • Added timezone-aware parsing for IB response timestamps in src/messages.rs, covering Unix timestamps, UTC-formatted yyyyMMdd-HH:mm:ss values, timestamps with embedded timezone names, session-local yyyyMMdd HH:mm:ss values, and date-only yyyyMMdd values when a session timezone is available.
  • Threaded decoder timezone context through head-timestamp and realtime market-data decoders so formatted IB timestamps can be interpreted correctly in both sync and async paths.
  • Tightened realtime stream handling by explicitly surfacing IncomingMessages::Error for realtime bars and by switching several decoder integer reads to message.next_optional_int()?.unwrap_or_default(), so omitted fields such as bar counts, tick attribute masks, market-depth positions, operations, and sides default to zero instead of failing on empty fields.
  • Expanded unit coverage for the new timestamp parsing rules and updated realtime-bar expectations to match UTC-formatted IB timestamps.

Design notes

  • UTC-formatted IB timestamps now decode as UTC regardless of the session timezone, which avoids offset-shifting values like 20260328-12:34:56.
  • Session-local parsing still uses the connected TWS/Gateway timezone, including rejection of ambiguous or nonexistent local times during DST transitions.
  • Date-only parsing is evaluated before the Unix-seconds fallback when session timezone context exists, preventing YYYYMMDD values from being misread as 1970-era epoch seconds.
  • Optional integer decoding now treats empty IB fields as unset and falls back to zero where the wire protocol leaves those values blank, which makes realtime and market-depth decoders more tolerant of incomplete messages without changing the decoded shape.

Testing

  • cargo test --features sync
  • cargo test --features async
  • cargo fmt --all

@faysou
Copy link
Copy Markdown
Contributor Author

faysou commented Apr 6, 2026

should I do the PR on top of v2-stable instead ?

wboayue added 5 commits April 8, 2026 22:01
- next_date_time delegates to next_date_time_with_timezone(None), remove parse_ib_date_time wrapper
- move StreamDecoder impls for BidAsk, MidPoint, Bar, Trade, MarketDepths, TickTypes from async.rs to mod.rs, remove cfg guards since one of sync/async is always enabled
Copy link
Copy Markdown
Owner

@wboayue wboayue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@wboayue wboayue merged commit e1333df into wboayue:main Apr 9, 2026
3 checks passed
wboayue added a commit that referenced this pull request Apr 9, 2026
* fix: handle IB formatted timestamps and optional realtime integer fields

* fix clippy needless_borrow warnings for NEW_YORK references

* deduplicate StreamDecoder impls and next_date_time method

- next_date_time delegates to next_date_time_with_timezone(None), remove parse_ib_date_time wrapper
- move StreamDecoder impls for BidAsk, MidPoint, Bar, Trade, MarketDepths, TickTypes from async.rs to mod.rs, remove cfg guards since one of sync/async is always enabled

* revert optional int decoding — C# reference uses ReadInt() for all fields

* rename decode_head_timestamp_with_timezone to decode_head_timestamp

* add embedded timezone tests, error on unrecognized tz, use skip() in tests, add double-space comment

---------

Co-authored-by: Wil Boayue <wil.boayue@gmail.com>
wboayue added a commit that referenced this pull request Apr 10, 2026
* clean up CLAUDE.md: fix clippy commands, remove duplication, reorder sections, add branches and doc maintenance policy

* fix: timezone-aware IB timestamp parsing and StreamDecoder dedup (#443)

* fix: handle IB formatted timestamps and optional realtime integer fields

* fix clippy needless_borrow warnings for NEW_YORK references

* deduplicate StreamDecoder impls and next_date_time method

- next_date_time delegates to next_date_time_with_timezone(None), remove parse_ib_date_time wrapper
- move StreamDecoder impls for BidAsk, MidPoint, Bar, Trade, MarketDepths, TickTypes from async.rs to mod.rs, remove cfg guards since one of sync/async is always enabled

* revert optional int decoding — C# reference uses ReadInt() for all fields

* rename decode_head_timestamp_with_timezone to decode_head_timestamp

* add embedded timezone tests, error on unrecognized tz, use skip() in tests, add double-space comment

---------

Co-authored-by: Wil Boayue <wil.boayue@gmail.com>

* require PRs for changes to main and v2-stable

* fix: add-british-summer-time-zone-mapping (#445)

* fix: add-british-summer-time-zone-mapping

* refactor timezone mapping to table-driven lookup

---------

Co-authored-by: kinz <keith.kinz@gmail.com>
Co-authored-by: Wil Boayue <wil.boayue@gmail.com>

* fix: improve error context for parsing failures (#440)

* fix(messages): improve error context for parsing failures

- Wrap parse() calls in next_date_time() with Error::Parse to include field index and value
- Fix parse_unix_timestamp() to provide error context instead of generic ParseIntError
- Fix parse_bar_date() to provide error context instead of generic ParseIntError

This changes error messages from:
  'invalid digit found in string'
to:
  'parse error: <field_index> - <field_value> - <parse_error>'

Making it much easier to debug which IBKR message field is causing parsing issues.

Fixes issues where symbols like GOOGL, BTC, QCOM fail during subscription with
opaque 'invalid digit found in string' errors.

* test: add coverage for parse_bar_date and parse_unix_timestamp

---------

Co-authored-by: Wil Boayue <wil.boayue@gmail.com>

* fix: propagate time-in-force to bracket order child orders (#444)

* bump version to 2.11.0

* refactor: move Client methods into domain modules

Move domain-specific impl Client methods from monolithic client/sync.rs
and client/async.rs into their respective domain modules (accounts,
contracts, orders, market_data, news, scanner, display_groups, wsh).

Eliminates standalone delegation functions and pub mod blocking
re-exports. New API methods no longer require touching the client files.

* docs: update for domain module pattern

Update CLAUDE.md, extending-api.md, and api-patterns.md to reflect that
Client methods now live as impl blocks in domain modules, not as
standalone functions with blocking re-exports.

* remove completed todo

* fix: make verify_contract an impl Client method for sync/async consistency

* deduplicate: extract shared logic to common modules

- Extract verify_contract to contracts/common/verify.rs (was duplicated
  in sync.rs and async.rs)
- Move StreamDecoder impls to common/stream_decoders.rs for orders,
  news, and scanner (were duplicated between sync.rs and async.rs with
  cfg gates)

* fmt: fix import ordering

* fix: gate sync-only test tables and remove unused imports for CI

* docs: match clippy flags to CI in CLAUDE.md

---------

Co-authored-by: faysou <faysal.aberkane@gmail.com>
Co-authored-by: Keith Liu <135390672+kinz-dev@users.noreply.github.com>
Co-authored-by: kinz <keith.kinz@gmail.com>
Co-authored-by: Vijay Singh <singhvjd@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants