Its a surprisingly hard problem
I have worked (in my spare time) on both calendar sync and contacts sync for many, many years. They are both really hard problems.
The main issue is that the standards (ICS, etc - and also all the proprietary ones) are interchange standards, not sync standards (mostly the difference is that they exchange data, not transactions). That is only a problem because devices and implementations differ - the standards envisage perfect devices, with infinite storage and up to date software.
To take a simple example... you have a phone calendar and you sync it to a desktop calendar. Then, on the phone you change something and resync. When the update happens, which should win? Well, it is obvious, you say, the most recent data wins. What if you have made two different (not even conflicting) changes on the two systems (maybe you deleted an attendee on the desktop and changed the meeting text on the phone)? The phone data is more recent (we are exchanging data, not transactions) so it wins and the attendee deletion is lost.
The problem gets even worse when multiway sync is happening between several devices. In fact, in that case it is so bad it is, in practice, essential to regard one of your systems as the primary (and sync small changes from other devices with the primary often) - that doesn't stop the problem but at least makes it possible to understand what is happening!
Unfortunately, even if the protocols are extended to address this (such as, for example, giving every item of data its own modification time) there is a much more serious problem in reality... the participating devices are not equal: in capabilities, in features, in storage, in reliability or in bugs.
Simple example is a phone with a simple dialing list: it might only store names and phone numbers, and maybe only one home number and one work number. What happens if your desktop has 2 work numbers, 2 mobiles, 1 home number, 1 holiday home number, for the contact? In this case, most phones will select a couple of the numbers and just throw away the rest -- that is the most user friendly choice as, in practice, people want their contact sync to succeed and not generate errors because obscure data is not being stored. If you later make a change on the phone and sync back how does the desktop know whether these other numbers were deliberately removed or just never received?
Back when I was a main contributor for both GPE (a PDA suite for early smart devices) and OpenSync (a very powerful and sophisticated PDA sync which tried to solve the PDA sync problem properly) [I didn't create either but I did put time in trying to make both work!] we tried really hard to solve these problems. For example, we had the concept of a database of all the quirks of all the PDA implementations so we could say "ah, that phone only stores 2 home phone numbers so if it reports only two later don't assume the others had been deleted". It never worked. It was just too complicated (and it could only have worked if OpenSync was the primary and everything else synced with that and never with each other).
In practice, the best solution today is to have something you consider the primary (often a desktop system like Evolution, or a storage solution like Nextcloud) and make sure you sync devices frequently, and try to limit changes to the primary if possible.