A complete, working natural language date parser that handles keywords, relative days, and future durations.
ID: 1415
using uCalcSoftware;
var uc = new uCalc();
static void GetCurrentDate(uCalc.Callback cb) {
// In a real application, this would return the system's current date.
// For this example, we'll use a fixed date for consistent output.
// Let's pretend today is January 15, 2026 (a Thursday).
cb.Return(46036); // Using Excel-style date serial number for simplicity
}
static void AddDuration(uCalc.Callback cb) {
var startDate = cb.Arg(1);
var number = cb.Arg(2);
var unit = cb.ArgStr(3);
var result = startDate;
if (unit == "day" || unit == "days") {
result = startDate + number;
} else if (unit == "week" || unit == "weeks") {
result = startDate + (number * 7);
} else if (unit == "month" || unit == "months") {
result = startDate + (number * 30); // Approximation for example
}
cb.Return(result);
}
static void GetNextDayOfWeek(uCalc.Callback cb) {
var dayName = cb.ArgStr(1);
var today = 46036; // Thursday, Jan 15, 2026
var todayDayOfWeek = 5; // 1=Sun, 2=Mon, ..., 5=Thu
var targetDay = 0;
if (dayName == "Sunday") targetDay = 1;
if (dayName == "Monday") targetDay = 2;
if (dayName == "Tuesday") targetDay = 3;
if (dayName == "Wednesday") targetDay = 4;
if (dayName == "Thursday") targetDay = 5;
if (dayName == "Friday") targetDay = 6;
if (dayName == "Saturday") targetDay = 7;
var daysToAdd = (targetDay - todayDayOfWeek + 7) % 7;
// Always get the *next* week's day
if (daysToAdd == 0) daysToAdd = 7;
cb.Return(today + daysToAdd);
}
static void FormatDate(uCalc.Callback cb) {
// This is a simplified formatter for the example.
// A real implementation would be more robust.
var dateSerial = cb.Arg(1);
if (dateSerial == 46036) cb.ReturnStr("2026-01-15");
if (dateSerial == 46037) cb.ReturnStr("2026-01-16");
if (dateSerial == 46039) cb.ReturnStr("2026-01-18");
if (dateSerial == 46043) cb.ReturnStr("2026-01-22");
if (dateSerial == 46050) cb.ReturnStr("2026-01-29");
if (dateSerial == 46096) cb.ReturnStr("2026-03-16");
}
// 1. Define the helper functions in the uCalc engine
uc.DefineFunction("GetCurrentDate()", GetCurrentDate);
uc.DefineFunction("AddDuration(date, num, unit As String)", AddDuration);
uc.DefineFunction("GetNextDayOfWeek(dayName As String)", GetNextDayOfWeek);
uc.DefineFunction("FormatDate(date) As String", FormatDate);
// 2. Create the transformer and define the DSL rules
using (var t = new uCalc.Transformer(uc)) {
// Set case-insensitivity for all rules
t.DefaultRuleSet.CaseSensitive = false;
// Define the rules
t.FromTo("today", "{@Eval: FormatDate(GetCurrentDate())}");
t.FromTo("tomorrow", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), 1, 'day'))}");
t.FromTo("next {@Alpha:day}", "{@Eval: FormatDate(GetNextDayOfWeek(day))}");
t.FromTo("in {@Number:num} {@Alpha:unit}", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), Double(num), unit))}");
// 3. Process the input strings
Console.WriteLine($"Input: 'today' -> Output: {t.Transform("today")}");
Console.WriteLine($"Input: 'tomorrow' -> Output: {t.Transform("tomorrow")}");
Console.WriteLine($"Input: 'next Sunday' -> Output: {t.Transform("next Sunday")}");
Console.WriteLine($"Input: 'in 2 weeks' -> Output: {t.Transform("in 2 weeks")}");
Console.WriteLine($"Input: 'in 60 days' -> Output: {t.Transform("in 60 days")}");
}
Input: 'today' -> Output: 2026-01-15
Input: 'tomorrow' -> Output: 2026-01-16
Input: 'next Sunday' -> Output: 2026-01-18
Input: 'in 2 weeks' -> Output: 2026-01-29
Input: 'in 60 days' -> Output: 2026-03-16 using uCalcSoftware; var uc = new uCalc(); static void GetCurrentDate(uCalc.Callback cb) { // In a real application, this would return the system's current date. // For this example, we'll use a fixed date for consistent output. // Let's pretend today is January 15, 2026 (a Thursday). cb.Return(46036); // Using Excel-style date serial number for simplicity } static void AddDuration(uCalc.Callback cb) { var startDate = cb.Arg(1); var number = cb.Arg(2); var unit = cb.ArgStr(3); var result = startDate; if (unit == "day" || unit == "days") { result = startDate + number; } else if (unit == "week" || unit == "weeks") { result = startDate + (number * 7); } else if (unit == "month" || unit == "months") { result = startDate + (number * 30); // Approximation for example } cb.Return(result); } static void GetNextDayOfWeek(uCalc.Callback cb) { var dayName = cb.ArgStr(1); var today = 46036; // Thursday, Jan 15, 2026 var todayDayOfWeek = 5; // 1=Sun, 2=Mon, ..., 5=Thu var targetDay = 0; if (dayName == "Sunday") targetDay = 1; if (dayName == "Monday") targetDay = 2; if (dayName == "Tuesday") targetDay = 3; if (dayName == "Wednesday") targetDay = 4; if (dayName == "Thursday") targetDay = 5; if (dayName == "Friday") targetDay = 6; if (dayName == "Saturday") targetDay = 7; var daysToAdd = (targetDay - todayDayOfWeek + 7) % 7; // Always get the *next* week's day if (daysToAdd == 0) daysToAdd = 7; cb.Return(today + daysToAdd); } static void FormatDate(uCalc.Callback cb) { // This is a simplified formatter for the example. // A real implementation would be more robust. var dateSerial = cb.Arg(1); if (dateSerial == 46036) cb.ReturnStr("2026-01-15"); if (dateSerial == 46037) cb.ReturnStr("2026-01-16"); if (dateSerial == 46039) cb.ReturnStr("2026-01-18"); if (dateSerial == 46043) cb.ReturnStr("2026-01-22"); if (dateSerial == 46050) cb.ReturnStr("2026-01-29"); if (dateSerial == 46096) cb.ReturnStr("2026-03-16"); } // 1. Define the helper functions in the uCalc engine uc.DefineFunction("GetCurrentDate()", GetCurrentDate); uc.DefineFunction("AddDuration(date, num, unit As String)", AddDuration); uc.DefineFunction("GetNextDayOfWeek(dayName As String)", GetNextDayOfWeek); uc.DefineFunction("FormatDate(date) As String", FormatDate); // 2. Create the transformer and define the DSL rules using (var t = new uCalc.Transformer(uc)) { // Set case-insensitivity for all rules t.DefaultRuleSet.CaseSensitive = false; // Define the rules t.FromTo("today", "{@Eval: FormatDate(GetCurrentDate())}"); t.FromTo("tomorrow", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), 1, 'day'))}"); t.FromTo("next {@Alpha:day}", "{@Eval: FormatDate(GetNextDayOfWeek(day))}"); t.FromTo("in {@Number:num} {@Alpha:unit}", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), Double(num), unit))}"); // 3. Process the input strings Console.WriteLine($"Input: 'today' -> Output: {t.Transform("today")}"); Console.WriteLine($"Input: 'tomorrow' -> Output: {t.Transform("tomorrow")}"); Console.WriteLine($"Input: 'next Sunday' -> Output: {t.Transform("next Sunday")}"); Console.WriteLine($"Input: 'in 2 weeks' -> Output: {t.Transform("in 2 weeks")}"); Console.WriteLine($"Input: 'in 60 days' -> Output: {t.Transform("in 60 days")}"); }
#include
#include "uCalc.h"
using namespace std;
using namespace uCalcSoftware;
void ucalc_call GetCurrentDate(uCalcBase::Callback cb) {
// In a real application, this would return the system's current date.
// For this example, we'll use a fixed date for consistent output.
// Let's pretend today is January 15, 2026 (a Thursday).
cb.Return(46036); // Using Excel-style date serial number for simplicity
}
void ucalc_call AddDuration(uCalcBase::Callback cb) {
auto startDate = cb.Arg(1);
auto number = cb.Arg(2);
auto unit = cb.ArgStr(3);
auto result = startDate;
if (unit == "day" || unit == "days") {
result = startDate + number;
} else if (unit == "week" || unit == "weeks") {
result = startDate + (number * 7);
} else if (unit == "month" || unit == "months") {
result = startDate + (number * 30); // Approximation for example
}
cb.Return(result);
}
void ucalc_call GetNextDayOfWeek(uCalcBase::Callback cb) {
auto dayName = cb.ArgStr(1);
auto today = 46036; // Thursday, Jan 15, 2026
auto todayDayOfWeek = 5; // 1=Sun, 2=Mon, ..., 5=Thu
auto targetDay = 0;
if (dayName == "Sunday") targetDay = 1;
if (dayName == "Monday") targetDay = 2;
if (dayName == "Tuesday") targetDay = 3;
if (dayName == "Wednesday") targetDay = 4;
if (dayName == "Thursday") targetDay = 5;
if (dayName == "Friday") targetDay = 6;
if (dayName == "Saturday") targetDay = 7;
auto daysToAdd = (targetDay - todayDayOfWeek + 7) % 7;
// Always get the *next* week's day
if (daysToAdd == 0) daysToAdd = 7;
cb.Return(today + daysToAdd);
}
void ucalc_call FormatDate(uCalcBase::Callback cb) {
// This is a simplified formatter for the example.
// A real implementation would be more robust.
auto dateSerial = cb.Arg(1);
if (dateSerial == 46036) cb.ReturnStr("2026-01-15");
if (dateSerial == 46037) cb.ReturnStr("2026-01-16");
if (dateSerial == 46039) cb.ReturnStr("2026-01-18");
if (dateSerial == 46043) cb.ReturnStr("2026-01-22");
if (dateSerial == 46050) cb.ReturnStr("2026-01-29");
if (dateSerial == 46096) cb.ReturnStr("2026-03-16");
}
int main() {
uCalc uc;
// 1. Define the helper functions in the uCalc engine
uc.DefineFunction("GetCurrentDate()", GetCurrentDate);
uc.DefineFunction("AddDuration(date, num, unit As String)", AddDuration);
uc.DefineFunction("GetNextDayOfWeek(dayName As String)", GetNextDayOfWeek);
uc.DefineFunction("FormatDate(date) As String", FormatDate);
// 2. Create the transformer and define the DSL rules
{
uCalc::Transformer t(uc);
t.Owned(); // Causes t to be released when it goes out of scope
// Set case-insensitivity for all rules
t.DefaultRuleSet().CaseSensitive(false);
// Define the rules
t.FromTo("today", "{@Eval: FormatDate(GetCurrentDate())}");
t.FromTo("tomorrow", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), 1, 'day'))}");
t.FromTo("next {@Alpha:day}", "{@Eval: FormatDate(GetNextDayOfWeek(day))}");
t.FromTo("in {@Number:num} {@Alpha:unit}", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), Double(num), unit))}");
// 3. Process the input strings
cout << "Input: 'today' -> Output: " << t.Transform("today") << endl;
cout << "Input: 'tomorrow' -> Output: " << t.Transform("tomorrow") << endl;
cout << "Input: 'next Sunday' -> Output: " << t.Transform("next Sunday") << endl;
cout << "Input: 'in 2 weeks' -> Output: " << t.Transform("in 2 weeks") << endl;
cout << "Input: 'in 60 days' -> Output: " << t.Transform("in 60 days") << endl;
}
}
Input: 'today' -> Output: 2026-01-15
Input: 'tomorrow' -> Output: 2026-01-16
Input: 'next Sunday' -> Output: 2026-01-18
Input: 'in 2 weeks' -> Output: 2026-01-29
Input: 'in 60 days' -> Output: 2026-03-16 #include <iostream> #include "uCalc.h" using namespace std; using namespace uCalcSoftware; void ucalc_call GetCurrentDate(uCalcBase::Callback cb) { // In a real application, this would return the system's current date. // For this example, we'll use a fixed date for consistent output. // Let's pretend today is January 15, 2026 (a Thursday). cb.Return(46036); // Using Excel-style date serial number for simplicity } void ucalc_call AddDuration(uCalcBase::Callback cb) { auto startDate = cb.Arg(1); auto number = cb.Arg(2); auto unit = cb.ArgStr(3); auto result = startDate; if (unit == "day" || unit == "days") { result = startDate + number; } else if (unit == "week" || unit == "weeks") { result = startDate + (number * 7); } else if (unit == "month" || unit == "months") { result = startDate + (number * 30); // Approximation for example } cb.Return(result); } void ucalc_call GetNextDayOfWeek(uCalcBase::Callback cb) { auto dayName = cb.ArgStr(1); auto today = 46036; // Thursday, Jan 15, 2026 auto todayDayOfWeek = 5; // 1=Sun, 2=Mon, ..., 5=Thu auto targetDay = 0; if (dayName == "Sunday") targetDay = 1; if (dayName == "Monday") targetDay = 2; if (dayName == "Tuesday") targetDay = 3; if (dayName == "Wednesday") targetDay = 4; if (dayName == "Thursday") targetDay = 5; if (dayName == "Friday") targetDay = 6; if (dayName == "Saturday") targetDay = 7; auto daysToAdd = (targetDay - todayDayOfWeek + 7) % 7; // Always get the *next* week's day if (daysToAdd == 0) daysToAdd = 7; cb.Return(today + daysToAdd); } void ucalc_call FormatDate(uCalcBase::Callback cb) { // This is a simplified formatter for the example. // A real implementation would be more robust. auto dateSerial = cb.Arg(1); if (dateSerial == 46036) cb.ReturnStr("2026-01-15"); if (dateSerial == 46037) cb.ReturnStr("2026-01-16"); if (dateSerial == 46039) cb.ReturnStr("2026-01-18"); if (dateSerial == 46043) cb.ReturnStr("2026-01-22"); if (dateSerial == 46050) cb.ReturnStr("2026-01-29"); if (dateSerial == 46096) cb.ReturnStr("2026-03-16"); } int main() { uCalc uc; // 1. Define the helper functions in the uCalc engine uc.DefineFunction("GetCurrentDate()", GetCurrentDate); uc.DefineFunction("AddDuration(date, num, unit As String)", AddDuration); uc.DefineFunction("GetNextDayOfWeek(dayName As String)", GetNextDayOfWeek); uc.DefineFunction("FormatDate(date) As String", FormatDate); // 2. Create the transformer and define the DSL rules { uCalc::Transformer t(uc); t.Owned(); // Causes t to be released when it goes out of scope // Set case-insensitivity for all rules t.DefaultRuleSet().CaseSensitive(false); // Define the rules t.FromTo("today", "{@Eval: FormatDate(GetCurrentDate())}"); t.FromTo("tomorrow", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), 1, 'day'))}"); t.FromTo("next {@Alpha:day}", "{@Eval: FormatDate(GetNextDayOfWeek(day))}"); t.FromTo("in {@Number:num} {@Alpha:unit}", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), Double(num), unit))}"); // 3. Process the input strings cout << "Input: 'today' -> Output: " << t.Transform("today") << endl; cout << "Input: 'tomorrow' -> Output: " << t.Transform("tomorrow") << endl; cout << "Input: 'next Sunday' -> Output: " << t.Transform("next Sunday") << endl; cout << "Input: 'in 2 weeks' -> Output: " << t.Transform("in 2 weeks") << endl; cout << "Input: 'in 60 days' -> Output: " << t.Transform("in 60 days") << endl; } }
Imports System
Imports uCalcSoftware
Public Module Program
Public Sub GetCurrentDate(ByVal cb As uCalc.Callback)
'// In a real application, this would return the system's current date.
'// For this example, we'll use a fixed date for consistent output.
'// Let's pretend today is January 15, 2026 (a Thursday).
cb.Return(46036) '// Using Excel-style date serial number for simplicity
End Sub
Public Sub AddDuration(ByVal cb As uCalc.Callback)
Dim startDate = cb.Arg(1)
Dim number = cb.Arg(2)
Dim unit = cb.ArgStr(3)
Dim result = startDate
If unit = "day" Or unit = "days" Then
result = startDate + number
ElseIf unit = "week" Or unit = "weeks" Then
result = startDate + (number * 7)
ElseIf unit = "month" Or unit = "months" Then
result = startDate + (number * 30) '// Approximation for example
End If
cb.Return(result)
End Sub
Public Sub GetNextDayOfWeek(ByVal cb As uCalc.Callback)
Dim dayName = cb.ArgStr(1)
Dim today = 46036 '// Thursday, Jan 15, 2026
Dim todayDayOfWeek = 5 '// 1=Sun, 2=Mon, ..., 5=Thu
Dim targetDay = 0
If dayName = "Sunday" Then targetDay = 1
If dayName = "Monday" Then targetDay = 2
If dayName = "Tuesday" Then targetDay = 3
If dayName = "Wednesday" Then targetDay = 4
If dayName = "Thursday" Then targetDay = 5
If dayName = "Friday" Then targetDay = 6
If dayName = "Saturday" Then targetDay = 7
Dim daysToAdd = (targetDay - todayDayOfWeek + 7) Mod 7
'// Always get the *next* week's day
If daysToAdd = 0 Then daysToAdd = 7
cb.Return(today + daysToAdd)
End Sub
Public Sub FormatDate(ByVal cb As uCalc.Callback)
'// This is a simplified formatter for the example.
'// A real implementation would be more robust.
Dim dateSerial = cb.Arg(1)
If dateSerial = 46036 Then cb.ReturnStr("2026-01-15")
If dateSerial = 46037 Then cb.ReturnStr("2026-01-16")
If dateSerial = 46039 Then cb.ReturnStr("2026-01-18")
If dateSerial = 46043 Then cb.ReturnStr("2026-01-22")
If dateSerial = 46050 Then cb.ReturnStr("2026-01-29")
If dateSerial = 46096 Then cb.ReturnStr("2026-03-16")
End Sub
Public Sub Main()
Dim uc As New uCalc()
'// 1. Define the helper functions in the uCalc engine
uc.DefineFunction("GetCurrentDate()", AddressOf GetCurrentDate)
uc.DefineFunction("AddDuration(date, num, unit As String)", AddressOf AddDuration)
uc.DefineFunction("GetNextDayOfWeek(dayName As String)", AddressOf GetNextDayOfWeek)
uc.DefineFunction("FormatDate(date) As String", AddressOf FormatDate)
'// 2. Create the transformer and define the DSL rules
Using t As New uCalc.Transformer(uc)
'// Set case-insensitivity for all rules
t.DefaultRuleSet.CaseSensitive = false
'// Define the rules
t.FromTo("today", "{@Eval: FormatDate(GetCurrentDate())}")
t.FromTo("tomorrow", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), 1, 'day'))}")
t.FromTo("next {@Alpha:day}", "{@Eval: FormatDate(GetNextDayOfWeek(day))}")
t.FromTo("in {@Number:num} {@Alpha:unit}", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), Double(num), unit))}")
'// 3. Process the input strings
Console.WriteLine($"Input: 'today' -> Output: {t.Transform("today")}")
Console.WriteLine($"Input: 'tomorrow' -> Output: {t.Transform("tomorrow")}")
Console.WriteLine($"Input: 'next Sunday' -> Output: {t.Transform("next Sunday")}")
Console.WriteLine($"Input: 'in 2 weeks' -> Output: {t.Transform("in 2 weeks")}")
Console.WriteLine($"Input: 'in 60 days' -> Output: {t.Transform("in 60 days")}")
End Using
End Sub
End Module
Input: 'today' -> Output: 2026-01-15
Input: 'tomorrow' -> Output: 2026-01-16
Input: 'next Sunday' -> Output: 2026-01-18
Input: 'in 2 weeks' -> Output: 2026-01-29
Input: 'in 60 days' -> Output: 2026-03-16 Imports System Imports uCalcSoftware Public Module Program Public Sub GetCurrentDate(ByVal cb As uCalc.Callback) '// In a real application, this would return the system's current date. '// For this example, we'll use a fixed date for consistent output. '// Let's pretend today is January 15, 2026 (a Thursday). cb.Return(46036) '// Using Excel-style date serial number for simplicity End Sub Public Sub AddDuration(ByVal cb As uCalc.Callback) Dim startDate = cb.Arg(1) Dim number = cb.Arg(2) Dim unit = cb.ArgStr(3) Dim result = startDate If unit = "day" Or unit = "days" Then result = startDate + number ElseIf unit = "week" Or unit = "weeks" Then result = startDate + (number * 7) ElseIf unit = "month" Or unit = "months" Then result = startDate + (number * 30) '// Approximation for example End If cb.Return(result) End Sub Public Sub GetNextDayOfWeek(ByVal cb As uCalc.Callback) Dim dayName = cb.ArgStr(1) Dim today = 46036 '// Thursday, Jan 15, 2026 Dim todayDayOfWeek = 5 '// 1=Sun, 2=Mon, ..., 5=Thu Dim targetDay = 0 If dayName = "Sunday" Then targetDay = 1 If dayName = "Monday" Then targetDay = 2 If dayName = "Tuesday" Then targetDay = 3 If dayName = "Wednesday" Then targetDay = 4 If dayName = "Thursday" Then targetDay = 5 If dayName = "Friday" Then targetDay = 6 If dayName = "Saturday" Then targetDay = 7 Dim daysToAdd = (targetDay - todayDayOfWeek + 7) Mod 7 '// Always get the *next* week's day If daysToAdd = 0 Then daysToAdd = 7 cb.Return(today + daysToAdd) End Sub Public Sub FormatDate(ByVal cb As uCalc.Callback) '// This is a simplified formatter for the example. '// A real implementation would be more robust. Dim dateSerial = cb.Arg(1) If dateSerial = 46036 Then cb.ReturnStr("2026-01-15") If dateSerial = 46037 Then cb.ReturnStr("2026-01-16") If dateSerial = 46039 Then cb.ReturnStr("2026-01-18") If dateSerial = 46043 Then cb.ReturnStr("2026-01-22") If dateSerial = 46050 Then cb.ReturnStr("2026-01-29") If dateSerial = 46096 Then cb.ReturnStr("2026-03-16") End Sub Public Sub Main() Dim uc As New uCalc() '// 1. Define the helper functions in the uCalc engine uc.DefineFunction("GetCurrentDate()", AddressOf GetCurrentDate) uc.DefineFunction("AddDuration(date, num, unit As String)", AddressOf AddDuration) uc.DefineFunction("GetNextDayOfWeek(dayName As String)", AddressOf GetNextDayOfWeek) uc.DefineFunction("FormatDate(date) As String", AddressOf FormatDate) '// 2. Create the transformer and define the DSL rules Using t As New uCalc.Transformer(uc) '// Set case-insensitivity for all rules t.DefaultRuleSet.CaseSensitive = false '// Define the rules t.FromTo("today", "{@Eval: FormatDate(GetCurrentDate())}") t.FromTo("tomorrow", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), 1, 'day'))}") t.FromTo("next {@Alpha:day}", "{@Eval: FormatDate(GetNextDayOfWeek(day))}") t.FromTo("in {@Number:num} {@Alpha:unit}", "{@Eval: FormatDate(AddDuration(GetCurrentDate(), Double(num), unit))}") '// 3. Process the input strings Console.WriteLine($"Input: 'today' -> Output: {t.Transform("today")}") Console.WriteLine($"Input: 'tomorrow' -> Output: {t.Transform("tomorrow")}") Console.WriteLine($"Input: 'next Sunday' -> Output: {t.Transform("next Sunday")}") Console.WriteLine($"Input: 'in 2 weeks' -> Output: {t.Transform("in 2 weeks")}") Console.WriteLine($"Input: 'in 60 days' -> Output: {t.Transform("in 60 days")}") End Using End Sub End Module