Some patients don’t know their exact date of birth. When that happens, staff can register the patient with an estimated age instead, and OpenMRS works out an approximate birthdate from it.
The problem
The same patient’s birthdate is shown differently in different parts of O3. For example, a patient registered on 14 October as “about 33 years old” shows the same age everywhere (33 yrs), but:
The day and month in search results aren’t real. The system fills them in when an age is estimated — in this case with the date the patient was registered; on other records it may be 1 January. The result looks like a genuine birthday (here it even suggests the patient’s birthday is today, 14-Oct), which can mislead staff who use date of birth to confirm they have the right patient. (Tracked in O3-6099.)
Why the two screens disagree
They get the patient’s details from two different places in the system:
The patient header uses the FHIR API (/ws/fhir2/R4/Patient/{uuid}). For an estimated birthdate, it only gives the year, e.g. "birthDate": "1993".
Patient search (both the search page and the search box in the top bar) uses the REST API (/ws/rest/v1/patient?q=…). It gives the full stored date (1993-10-14) together with a separate “estimated” flag. The search screen shows the full date and doesn’t use that flag.
(Search results are converted to FHIR format in the browser for display, but the underlying data comes from REST.)
Why this isn’t a quick fix
OpenMRS stores every birthdate as a full date, plus a simple yes/no flag saying whether it’s estimated. It doesn’t record which part is uncertain — the day, the month, or the year.
Earlier design ideas, such as showing question marks for the unknown parts, never made it into the product.
So, we’d like to agree on the right behaviour with the community first.
What we’d like to hear from you
How should an estimated birthdate look? For example:
Year only: 1993
With a marker: ~1993 or 1993 (est.)
Question marks for unknown parts: ??-??-1993(this would need the data model change in question 3)
Age only: ~33 yrs
Something else?
Should the age also show it’s estimated (e.g. ~33 yrs)?
Is “estimated: yes/no” enough? Or do you need to record partial knowledge, such as knowing the month and year but not the day?
Where does it need to be consistent? Patient header, search results, registration, printed labels and forms?
How do you handle this today? Paper conventions, local customisations, or national requirements?
Does anything clinical depend on it at your sites, such as children’s dosing or growth charts?
Thanks for writing this up, @veronica. A few things I found poking at this locally:
FHIR doesn’t always return just the year. For kids under 6 it returns the month too (2024-03), so the banner shows Mar 2024 (BirthDateTranslatorImpl). A code comment there says the cutoff was picked to line up with the WHO and CDC growth charts, so it’s worth checking with implementers whether it works for them.
On display, I’d probably show whatever precision the API returns plus a marker, e.g. 1993 (est.). The RefApp 2.x header used a ~ for this. I’d skip ??-??-1993 since it suggests we know the year, and an estimated age doesn’t tell us that either.
The age should show it’s estimated too. It’s the number the clerk actually estimated, and it isn’t stable across screens. The banner works it out from the year alone, so it ticks over on 1 January, while the backend uses the full stored date. For someone with an estimated birthdate stored as 01-Dec-1992, the banner says 34 yrs right now while the backend says 33.
Registration asks for the estimated age in years and months, but we don’t keep what was entered, so we’d need to capture the precision explicitly and store it alongside the estimated flag. That would let FHIR return what we actually know. It’s a core change though, so it’s probably better to agree on display first.
#2825 is working on getting search to match the banner. It’s probably best to keep it to that and settle the rest here.
I would favor 1993. Showing a year without a specific day implies an estimate. Something like (est.) would need localization support.
Birthdate should always show a date (even if it’s a partial/estimated date), so I would never show ~33 yrs for a birthdate. That’s an age, not a birthdate.
Should the age also show it’s estimated (e.g., ~33 yrs)? Yes! Technically speaking, if we do (with item #3) eventually get to a point where we can distinguish ??-May-1993 from ??-??-1993, then the ~ would only be needed in May in the former case.
Is “estimated: yes/no” enough?
If we’re going to make an improvement to any partial date support on the backend, I still support my proposal for a permanent fix for managing partial dates for a comprehensive support for partial dates and would suggest we take that approach, even if we tackle it one field at a time.
Where does it need to be consistent? Everywhere. Consistency is a foundation of good UX.
How do you handle this today? I’ll let implementers speak to this. The EMR I use in clinic supports partial dates for diagnoses and it’s great. I can put an exact date, month & year, or just year and it saves whatever I’ve entered, showing 15-May-1993, May-1993 or 1993.
Does anything clinical depend on it at your sites? Birthdate precision matters more for children. It also can affect reporting, which is an argument for storing midpoints instead of defaulting to 1 for missing information (e.g., storing May-1993 as 15-May-1993 and 1993 as 15-Jun-1993 – or 2-Jul-1993 – instead of 1-May-1993 and 1-Jan-1993). Comprehensive support for partial dates would fix – or at least provide reliable & explicit solutions for – all of these problems.
Quick update on the O3 side. #2825 is merged, so the search page and the search box in the top bar now show what the header shows (1993, or Mar 2024 for under-6s).
I also went looking for other screens that still show a made-up day and month, and found four. Each has a PR up:
The checked-in patients list in the “Add patient to queue” workspace had the same bug as search. It used the full stored date from the REST API and didn’t request the estimated flag, so a patient registered on 26 October with an estimated age of 40 showed as born on 26-Oct-1986: openmrs-esm-patient-management#2843
The patient details tile in the visit and visit note forms, and the drug order form header: openmrs-esm-patient-chart#3833
The tile, drug order header and appointment details get the partial date from the FHIR API but turn it back into a full one, so 1993 shows as 01-Jan-1993. With all of these in, every screen I could find preserves the same birthdate precision, which gets us closer to @burke’s “everywhere”, whichever display we pick.
One side effect of #2825 worth knowing about. Search now works out the age from the same partial date as the header, so it picks up the age quirks I mentioned above. For adults that’s the 1 January tick-over (an estimated 01-Dec-1992 shows 34 yrs in both places now, while the backend says 33). For under-6s it’s a bit worse. With only a month to go on, the age is worked out as if the birthday fell on today’s day of that month, so a baby with Aug 2026 shows 8 wks, 5 days for all of October and then jumps to 13 wks, 1 day on 1 November. Weeks and days is probably more precision than we have for an age we only know to the month, which is another point for marking estimated ages.
The upside is that the header, search and the checked-in patients list already render the birthdate through the same banner component in core, so a ~ (or whatever we settle on) could go there for all three. The tile, drug order header and appointment details would still need the same treatment. With our current FHIR mapping, a partial date (YYYY or YYYY-MM) is enough to tell a birthdate is estimated. Registration already uses this when editing a patient.
Thanks Dennis, really useful round-up, and the age examples make the case for marking estimated ages well.
One more screen with the same bug (Jira): the printed invoice in the billing app still turns a partial birthdate into a full one (01-Jan-1993). See example