Prescribing Frequencies: The FHIR Way
Understanding this is a frequent request 😎, now revealed!​
How It Works​
This document explains how our prescription frequencies should be stored in MedicationRequest and in ServiceRequest
FHIR resource. Mona 3 architecture will support the all possibilities FHIR provides to store and process various frequencies.
Frequencies have a correlation with how Task-List will be generated hence, Mona 2 will only have limited possibilities to
store and process various frequencies.
Self-Sufficient Prescriptions with Full FHIR Frequency Storage​
The primary goal of storing comprehensive frequency information directly within FHIR resources (like MedicationRequest
and ServiceRequest) is to make them self-sufficient.
âš¡ Performance Boost: By having all frequency-related details readily available, we eliminate the need for
time-consuming lookups in external Terminology DB tables such as FrequencyTime and PrescriptionFrequencies.
This offers several key advantages:
-
Faster Processing: When handling FHIR resources or generating Task-List recommendations, all necessary frequency data is immediately accessible. Say goodbye to delays caused by terminology database queries!
-
Improved UI Responsiveness: The user interface can directly display the correct, user-friendly names for various frequencies without making extra calls to terminology endpoints. This results in a smoother and more efficient user experience.
-
Future-Proof External Integration: 🔗 In the future, external services will be able to directly interpret the frequency information within the FHIR resource itself, enhancing interoperability and reducing dependencies.
✅ Key Benefit: Making FHIR resources self-contained with complete frequency information streamlines data access, boosts performance, and facilitates easier integration with external systems.
Mona frequencies​
Timing Structure​
The Timing data type in FHIR is used to describe the occurrence of an event that may happen multiple times. It specifies when events are expected or requested to occur and can also summarize past or ongoing events. While the definitions of Timing components often refer to 'future' events for simplicity, they can also describe historic or ongoing events.
A Timing schedule can include:
- A list of specific events (using event).
- Criteria for when the event happens, expressed in a structured form (using repeat).
- A code representing a common timing pattern (using code).
- When both a list of events and a repeating specification are provided, the event list clarifies the information in the repeat structure.
{
// from BackboneElement: extension, modifierExtension
"event" : ["<dateTime>"], // When the event occurs
"repeat" : { // When the event is to occur
// bounds[x]: Length/Range of lengths, or (Start and/or end) limits. One of these 3:
"boundsDuration" : { Duration },
"boundsRange" : { Range },
"boundsPeriod" : { Period },
"count" : "<positiveInt>", // Number of times to repeat
"countMax" : "<positiveInt>", // Maximum number of times to repeat
"duration" : <decimal>, // How long when it happens
"durationMax" : <decimal>, // How long when it happens (Max)
"durationUnit" : "<code>", // s | min | h | d | wk | mo | a - unit of time (UCUM)
"frequency" : "<positiveInt>", // Event occurs frequency times per period
"frequencyMax" : "<positiveInt>", // Event occurs up to frequencyMax times per period
"period" : <decimal>, // Event occurs frequency times per period
"periodMax" : <decimal>, // Upper limit of period (3-4 hours)
"periodUnit" : "<code>", // s | min | h | d | wk | mo | a - unit of time (UCUM)
"dayOfWeek" : ["<code>"], // mon | tue | wed | thu | fri | sat | sun
"timeOfDay" : ["<time>"], // Time of day for action
"when" : ["<code>"], // Code for time period of occurrence
"offset" : "<unsignedInt>" // Minutes from event (before or after)
},
"code" : { CodeableConcept } // BID | TID | QID | AM | PM | QD | QOD | +
}
Constraints​
The following rules apply to the Timing.repeat element:
- If
durationis present,durationUnitmust also be present. - If
periodis present,periodUnitmust also be present. durationmust be a non-negative value.periodmust be a non-negative value.- If
periodMaxis present,periodmust also be present. - If
durationMaxis present,durationmust also be present. - If
countMaxis present,countmust also be present. - If
offsetis present,whenmust be present, andwhencannot be one of'C','CM','CD', or 'CV'. timeOfDayandwhencannot both be present.
Key Difference: There's a difference in how timing information is stored between MedicationRequest and ServiceRequest, which is important to understand for data consistency.
MedicationRequest: Timing is located within the dosageInstruction field. dosageInstruction is an array. Each element in the dosageInstruction array represents a Dosage, and a Dosage object holds the Timing details. This array structure allows for specifying multiple dosage instructions, each with its own timing.
ServiceRequest: Timing is stored in the occurrenceTiming field. occurrenceTiming is a single object. This single-object structure means that ServiceRequest can only represent one timing schedule. It does not inherently support multiple, distinct timing occurrences.
Mona frequencies and their correlation with Task-List​
There are the below types of frequencies we used in our Mona application:
MinutelyHourlyDailyWeeklyOnceContinuousAs-Needed
Minutely, Hourly, Daily, Weekly, Once and Custom prescription frequencies generate tasks, while Continuous and
As-Needed* do not.
Special Case for As-Needed:
Frequency type, As-Needed prescriptions do not generate tasks, even though they also contain frequency information within their Timing object in the FHIR resource.
Essential Fields and rules of Frequency Timing in Task-List generation​
boundsDurationcountperiodperiodUnitdayOfWeektimeOfDay
Important Rules!​
- Supported
periodUnitfor task list generation are:min | h | d | wk - Frequencies like
HourlyandMinutelytask list recommendation will always start from theboundsPeriod'sstarttime. - For task-list generation
frequencyandperiodshould be non-negative and non-zero value. - For
Dailyfrequency the number of entries intimeOfDayshould match with thefrequencyvalue. - For
Weeklyfrequency the number of entries indayOfWeekshould match with thefrequencyvalue. - For
Oncefrequency it is require to have exactly one entry present intimeOfDayits optional to have one entry indayOfWeekpresent. If onlytimeOfDayis present task-list recommendation generated for the next immediate possible time which is in betweenstartandendmentioned inboundsPeriodIf bothtimeOfDayanddayOfWeekpresent task-list recommendation generated for the next possible day mentioned in thedayOfWeekand time mentioned in thetimeOfDaywhich is also in between thestartandendmentioned inboundsPeriod. - Task-list recommendation will not be generated if the
counthas any other value than the1. - If
countis presentfrequency,periodandperiodunitis optional.
Common Fields for Frequency Timing​
For all frequency types, the start and end dates of the prescription are typically stored within the boundsPeriod object under the repeat property of the timing element:
- The
startfield withinboundsPeriodis required, indicating when the prescription becomes active. - The
endfield withinboundsPeriodis optional, specifying when the prescription should cease. If omitted, it implies the prescription continues indefinitely or until otherwise specified.
Minutely Frequency​
For prescriptions with a minutely frequency, the repeat object within the timing element will have the following properties:
periodUnit: This will always be set to"min"to denote hours.frequency: This will always be1, indicating one event per the definedperiod.period: This numerical value specifies the interval in minutes between administrations. For example,30.0indicates a frequency of every 30 minutes.
Example
- MedicationRequest
- ServiceRequest
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2025-07-01T00:00:00Z"
},
"frequency": 1,
"period": 30.0,
"periodUnit": "min"
}
}
]
}
{
"occurrenceTiming": {
"repeat": {
"boundsPeriod": {
"start": "2025-05-06T13:32:04.216Z",
"end": "2026-01-01T00:00:00Z"
},
"frequency": 1,
"period": 30.0,
"periodUnit": "min"
}
}
}
Hourly Frequency​
For prescriptions with an hourly frequency, the repeat object within the timing element will have the following properties:
periodUnit: This will always be set to"h"to denote hours.frequency: This will always be1, indicating one event per the definedperiod.period: This numerical value specifies the interval in hours between administrations. For example,4.0indicates a frequency of every 4 hours.
Example
- MedicationRequest
- ServiceRequest
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2025-07-01T00:00:00Z"
},
"frequency": 1,
"period": 4.0,
"periodUnit": "h"
}
}
]
}
{
"occurrenceTiming": {
"repeat": {
"boundsPeriod": {
"start": "2025-05-06T13:32:04.216Z",
"end": "2026-01-01T00:00:00Z"
},
"frequency": 1,
"period": 4.0,
"periodUnit": "h"
}
}
}
Generating Task-List Recommendations:
When generating task-list recommendations for hourly frequencies, the start and end dates from the boundsPeriod
are the primary drivers. It's important to note that the start and end date-time values can include minutes and
seconds that are not rounded off.
Task list recommendations for hourly frequencies should be generated precisely based on the start time provided
in the boundsPeriod. For an hourly frequency with a period of 4 hours and a start time of 2025-04-28T07:10:41.138Z,
the subsequent task recommendations will be scheduled by adding the period (in hours) to the initial start time.
This results in timestamps like:
2025-04-28T07:10:41.138Z
2025-04-28T11:10:41.138Z
2025-04-28T15:10:41.138Z
... and so on, every four hours.
Daily and/or Custom Frequency​
For prescriptions with a daily or custom frequency, the repeat object within the timing element will have the following properties:
periodUnit: This will always be set to"d"to denote days.period: This will always be1, indicating that the frequency is applied over a one-day period.frequency: This numerical value specifies how many times the event should occur within that single day. For example, a value of4signifies four administrations per day.timeOfDay: This is an array of strings, where each string represents a specific time of day when the medication should be administered. The time is stored in"HH:MM:ss"format (e.g.,"06:00:00"for 6:00 AM).
Distinction between Daily and Custom Frequencies:
The primary difference between "Daily" and "Custom" frequencies lies in how the timeOfDay array is populated:
-
Daily Frequency: The times listed in
timeOfDayare typically fetched from a predefined list will be available as the template or DB table or a map (yet to be defined!) -
Custom Frequency: The times in
timeOfDayare specified directly by the user, allowing for more flexible and individualized dosing schedules.
It's important to note that the times stored in the timeOfDay array are in the server's local time.
Example
- MedicationRequest
- ServiceRequest
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2025-07-01T00:00:00Z"
},
"frequency": 4,
"period": 1,
"periodUnit": "d",
"timeOfDay": [
"06:00:00",
"08:00:00",
"15:00:00",
"20:00:00"
]
}
}
]
}
{
"occurrenceTiming": {
"repeat": {
"boundsPeriod": {
"start": "2025-05-06T13:39:26.634Z",
"end": "2026-01-01T00:00:00Z"
},
"frequency": 4,
"period": 1.0,
"periodUnit": "d",
"timeOfDay": [
"06:00:00",
"08:00:00",
"15:00:00",
"20:00:00"
]
}
}
Generating Task-List Recommendations:
To generate the task list for Daily and Custom frequencies, the system iterates through the timeOfDay array. For each
day within the boundsPeriod (from the start date to the end date), a task recommendation is created for each time
specified in the timeOfDay array. The date for each recommendation will increment daily, while the time will be taken
from the timeOfDay entries.
Weekly Frequency​
For prescriptions with a weekly frequency, the repeat object within the timing element will have the following properties:
periodUnit: This will always be set to"wk"to denote days.period: This will always be1, indicating that the frequency is applied over a one-week period.frequency: This numerical value specifies how many times the event should occur within that single week. For example, a value of4signifies four administrations per week.timeOfDay: This is an array of strings, where each string represents a specific time of day when the medication should be administered. The time is stored in"HH:MM:ss"format (e.g.,"06:00:00"for 6:00 AM).dayOfWeek: This is an array of strings, where each string represents a specific day of the week when the medication should be administered. The day string should be from one of the following optionsmon | tue | wed | thu | fri | sat | sun
It's important to note that the times stored in the timeOfDay array are in the server's local time.
Example
- MedicationRequest
- ServiceRequest
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T11:53:17.490Z",
"end": "2026-01-01T00:00:00Z"
},
"frequency": 2,
"period": 1.0,
"periodUnit": "wk",
"timeOfDay": [
"14:00:00"
],
"dayOfWeek": [
"mon",
"wed"
]
}
}
]
}
{
"occurrenceTiming": {
"repeat": {
"boundsPeriod": {
"start": "2025-05-06T13:45:02.462Z",
"end": "2026-01-01T00:00:00Z"
},
"frequency": 2,
"period": 1.0,
"periodUnit": "wk",
"timeOfDay": [
"14:00:00"
],
"dayOfWeek": [
"mon",
"wed"
]
},
}
}
Generating Task-List Recommendations for Weekly Frequencies:
To create the task list for prescriptions with weekly frequencies, the system utilizes both the timeOfDay and
dayOfWeek arrays.
For each day within the specified boundsPeriod (spanning from the start date to the end date), the system checks
if that day matches any of the days listed in the dayOfWeek array.
If a match is found, a task list recommendation is generated for each time specified in the timeOfDay array for that
particular day.
The date of each recommendation will increment daily as the system iterates through the boundsPeriod. The specific
day of the week for the recommendation will be determined by the dayOfWeek array, and the time of day will be taken
from the timeOfDay array.
Important Limitation!
If a prescription requires different administration times on different days of the week (e.g., Monday at 10:00:00 and Wednesday at 14:00:00), this cannot be achieved with a single frequency (Timing object). Task-List will account for it and generate the recommendations accordingly.
To handle such scenarios, it is necessary to create two separate frequency (Timing object), one for each day of the week with its specific time of day.
Note: Only the MedicationRequest FHIR resource supports multiple frequencies via dosageInstruction.
This does not apply to the ServiceRequest FHIR resource.
Once frequency (Einmalig)​
For prescriptions with a once frequency, the repeat object within the timing element will have the following properties:
timeOfday: This is an array of strings, where each string represents a specific time of day when the medication should be administered. The time is stored in"HH:MM:ss"format (e.g.,"06:00:00"for 6:00 AM). It should not have more than one string present in the array, as it should be administered only once.count: It will always be set to1indicating only one time to be administered.
Example
- MedicationRequest
- ServiceRequest
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2026-01-01T00:00:00Z"
},
"timeOfDay": [
"06:00:00"
],
"dayOfWeek": ["mon"],
"count": 1
}
}
}
]
}
{
"occurrenceTiming": {
"repeat": {
"boundsPeriod": {
"start": "2025-05-06T13:51:18.964Z",
"end": "2026-01-01T00:00:00Z"
}
},
"timeOfDay": [
"06:00:00"
],
"dayOfWeek": ["mon"],
"count": 1
}
}
Generating Task-List Recommendations for "Once" Frequency:
For prescriptions with a "once" frequency, the system refers to the time specified in the timeOfDay array. A task list
recommendation will be generated only once within the entire duration defined by the boundsPeriod. This single
recommendation will occur on the start date of the boundsPeriod at the time specified in the timeOfDay array.
As-needed (Bei Bedarf) Frequency​
For prescriptions with an as-needed frequency, the timing object will have a boolean field named asNeededBoolean. For
as-needed frequency it will always be true and along with Ãt repeat object within timing object will have boundsPeriod
Example
- MedicationRequest
- ServiceRequest
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T11:17:03.167Z",
"end": "2026-01-01T00:00:00Z"
}
}
},
"asNeededBoolean": true
}
]
}
{
"occurrenceTiming": {
"repeat": {
"boundsPeriod": {
"start": "2025-05-06T13:54:44.713Z",
"end": "2026-01-01T00:00:00Z"
}
}
},
"asNeededBoolean": true
}
Task-list recommendation for the as-needed frequency will not be generated.
Continuous Frequency​
For prescriptions with a continuous frequency, the repeat object within timing object will only have boundsPeriod.
Example
- MedicationRequest
- ServiceRequest
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2026-01-01T00:00:00Z"
}
}
}
}
]
}
{
"occurrenceTiming": {
"repeat": {
"boundsPeriod": {
"start": "2025-05-06T13:58:06.586Z",
"end": "2026-01-01T00:00:00Z"
}
},
"code": {,
"text": "Kontinuierlich"
}
}
}
Task-list recommendation for the continuous frequency will not be generated.
Bonus: Intermittent Infusion​
Intermittent Infusion is handled similarly as Daily and/or Weekly frequencies. Only difference here is Intermittent Infusion contains
duration and durationUnit attributes. They have no direct relation with the task-list. Duration should be interpreted as how much long a
medication should be administered.
Example
- MedicationRequest
- ServiceRequest
{
"dosageInstruction": [
{
"timing": {
"repeat": {
"boundsPeriod": {
"start": "2025-04-28T07:10:41.138Z",
"end": "2026-01-01T00:00:00Z"
},
"timeOfDay": [
"06:00:00"
],
"dayOfWeek": ["mon"],
"duration": 30,
"durationUnit": "min"
}
}
}
]
}
{
"occurrenceTiming": {
"repeat": {
"boundsPeriod": {
"start": "2025-05-06T13:51:18.964Z",
"end": "2026-01-01T00:00:00Z"
}
},
"timeOfDay": [
"06:00:00"
],
"dayOfWeek": ["mon"],
"duration": 45,
"durationUnit": "min"
}
}
Appendix​
Examples of common uses of the Timing Data Type criteria from FHIR documentation​
| description | duration | durationUnit | frequency | frequencyMax | period | periodUnit | periodMax | when | bounds[x] | code |
|---|---|---|---|---|---|---|---|---|---|---|
| Every 8 hours | 8 | h | ||||||||
| Every 7 days | 7 | d | ||||||||
| 3 times a day | 3 | 1 | d | TID | ||||||
| 3-4 times a day | 3 | 4 | 1 | d | ||||||
| Every 4-6 hours | 4 | h | 6 | |||||||
| Every 21 days for 1 hour | 1 | hr | 21 | d | ||||||
| Three times a week for ½ hour | 0.5 | hr | 3 | 1 | wk | |||||
| With breakfast | CM | |||||||||
| For 5 minutes, 10 minutes before meals | 5 | min | AC | |||||||
| 1 tablet 3 times daily, 30 minutes before meals | 3 | 1 | d | AC | ||||||
| BID, 30 mins before meal, for next 10 days | 2 | 1 | d | AC | boundsPeriod.end = +10d | BID | ||||
| Duration = 10 days TID, for 14 days | 3 | 1 | d | boundsPeriod.end = +14d | TID | |||||
| Duration = 14 days BID, start on 7/1/2015 at 1:00 PM | 2 | 1 | d | boundsPeriod.start = 2015-07-01T13:00:00 | BID | |||||
| Mon, Wed, Fri Morning | 1 | d | MORN | dayOfWeek = mon, wed, fri | ||||||
| Every day at 10am | 1 | d | timeOfDay = 10:00 | |||||||
| Take once, at any time | 1 | |||||||||
| Take every second day, in the morning, until 20 have been taken | 2 | d | MORN | bounds[x].count = 20 | ||||||
| Twice a day, starting 2024-01-15, ending 2024-01-22 | 2 | 1 | d | boundsPeriod.start = 2024-01-15, boundsPeriod.end = 2024-01-22 | BID | |||||
| Daily at 9am, 1pm, and 5pm | 3 | 1 | d | timeOfDay = 09:00, 13:00, 17:00 | ||||||
| Every other week, on Tuesdays | 1 | 2 | wk | dayOfWeek = tue | QOD | |||||
| Three times a day for ten days | 3 | 1 | d | boundsDuration = 10 d | TID |