Over my 25+ years of programming, being able to estimate my time was the last and hardest thing for me to learn how to do.
No matter how much you've mastered computer science and how many clever encryption algorithms you're capable of writing, estimating how much time your work will take is a completely separate ability having nothing to do with your actual programming and/or mathematical skills.
It is possible for every programmer to learn how to do. It's not something you'll figure out in a week or a year or ten years. I promise you that being able to deliver your software on time, every time, will make you the most beloved programmer at your company.
The key is to, instead of jumping right into the coding, spend several days understanding exactly what work you need to do. Learn to be realistic about your abilities. Learn how to communicate with non-programmers so they understand exactly what they're getting. Keep explaining until it's clear that they understand what you're writing for them, and that's exactly what you're writing for them.
When people throw changes at you, warn them that you'll have to start from scratch with understanding exactly the new work that needs to be done, think about the time those changes will take knowing that you may need to discard work you've already done, and continue to be realistic about your abilities. Make sure you get approval for the revised completion time before starting any work. Do not jump right into coding the changes.
If your employer doesn't allow you do to this, quit and go work somewhere else. There is an oversupply of programming work.
Time estimates are something that all professionals do. When you finish your work on time, you are acting professionally. When you reject estimates you look like a rank amateur and I'd never hire you.