¿Analizador de fecha/hora en lenguaje natural para .NET?[cerrado]
Pregunta
¿Alguien sabe de un analizador de fecha/hora .NET similar a Crónica para Ruby (¿Maneja cosas como "mañana" o "3:00 p. m. el próximo jueves")?
Nota:Escribo Ruby (que es como sé sobre Chronic) pero este proyecto debe usar .NET.
Solución
Desarrollamos exactamente lo que buscas en un proyecto interno.Estamos pensando en hacerlo público si hay suficiente necesidad.Echa un vistazo a este blog para más detalles: http://precisionsoftwaredesign.com/blog.php.
No dudes en ponerte en contacto conmigo si estás interesado:contacto@precisionsoftware.us
Esta biblioteca es ahora un proyecto de SourceForge.La página está en:
http://www.SourceForge.net/p/naturaldate
El ensamblaje está en la sección de descargas y la fuente está disponible con Mercurial.
Otros consejos
No lo hago, pero hay un puerto Java llamado jcrónico.Al menos, podría proporcionar un buen punto de partida para el suyo.O tal vez podrías usar un traductor semiautomático de Java a C# como Pulpo para ayudar a traducirlo.(O algo mejor, si alguien sabe algo).
Bien, otra posible vía:¿Podrías usar el código crónico usando? hierrorubí?
Existe una adaptación .NET de Chronic.Ver https://github.com/robertwilczynski/nChronic.Creé una bifurcación con algunas mejoras y correcciones de errores, aquí: https://github.com/dorony/nChronic (Envié solicitudes de extracción, el autor aún no ha respondido).
@Blair Conrad - ¡Buenas ideas!Intenté ejecutar Chronic en IronRuby pero tuve algunos problemas con las dependencias; no sé si está listo todavía.
Encontré un proyecto en Códigoplex (DateTimeEnglishParser) que intenta hacer lo mismo.Aún no abarca años ni tiempo, pero es un buen comienzo.Trabajé un poco en el proyecto y contribuí con un parche para manejar mejor los números escritos.
Es un problema interesante y definitivamente me ha ayudado a comprender mejor las expresiones regulares, así que creo que seguiré trabajando en ello.
Hubo un hilo similar anteriormente y proporcionó un enlace a una biblioteca en CodeProject que parece hacer lo que desea: http://www.codeproject.com/KB/edit/dateparser.aspx pero desafortunadamente la biblioteca parece estar escrita en MFC, por lo que tendría que crear una DLL y luego llamarla desde su programa .NET.
Palmsey, recientemente tuve el mismo requisito, así que seguí adelante y escribí un analizador simple.No es el código más bonito pero manejará cosas como:
"Hoy a las 2pm" "Martes a las 2pm - 15 de julio de 2010 a las 2 a.m." "Año anterior a las 2 a.m. - mañana a las 14:30" "18 de julio de 2010 a las 2:45 p.m."
Pégalo en Codeplex porque tal vez alguien más lo encuentre útil.Échale un vistazo: http://timestamper.codeplex.com/
He comprobado varios frameworks y Python. Analizar fecha y hora funcionó mejor.Se puede utilizar desde .NET usando IronPython.
Si alguien está interesado en un proyecto de muestra completo, comente la respuesta e intentaré crear uno.
EDITAR
Según lo solicitado, aquí hay un proyecto simple que puede usar con la biblioteca:
http://www.assembla.com/code/relativedateparser/subversion/nodes
Pruebe el siguiente caso de uso, por ejemplo:
- 25 de agosto de 2008
- 25 de agosto de 2008
- 25 de agosto 17:00
- 5 p.m. 25 de agosto
- el próximo sábado
- mañana
- el próximo jueves a las 16 h
- a las 4 pm
- eod
- mañana fin de semana
- martes fin de semana
- eoy
- emom
- en 5 minutos
- dentro de 5 minutos
- 5 horas antes de ahora
- 2 horas antes del mediodía
- 2 días a partir de mañana
No conozco ninguno, pero parecía un problema interesante, así que aquí está mi solución (VB.NET):
Private Function ConvertDateTimeToStringRelativeToNow(ByVal d As DateTime) As String
Dim diff As TimeSpan = DateTime.Now().Subtract(d)
If diff.Duration.TotalMinutes < 1 Then Return "Now"
Dim str As String
If diff.Duration.TotalDays > 365 Then
str = CInt(diff.Duration.TotalDays / 365).ToString() & " years"
ElseIf diff.Duration.TotalDays > 30 Then
str = CInt(diff.TotalDays / 30).ToString() & " months"
ElseIf diff.Duration.TotalHours > 24 Then
str = CInt(diff.Duration.TotalHours / 24) & " days"
ElseIf diff.Duration.TotalMinutes > 60 Then
str = CInt(diff.Duration.TotalMinutes / 60) & " minutes"
Else
str = CInt(diff.Duration.TotalMinutes).ToString() & " minutes"
End If
If str.StartsWith("1") Then str = str.SubString(0, str.Length - 1)
If diff.TotalDays > 0 Then
str &= " ago"
Else
str &= " from now"
End If
Return str
End Function
Realmente no es tan sofisticado como los que ya existen, pero supongo que funciona bien.Podría ser un buen método de extensión.
@Burton:Creo que quiso decir lo contrario, al menos según el ejemplo de la página vinculada:
Chronic.parse('tomorrow')
#=> Mon Aug 28 12:00:00 PDT 2006
Chronic.parse('monday', :context => :past)
#=> Mon Aug 21 12:00:00 PDT 2006
Chronic.parse('this tuesday 5:00')
#=> Tue Aug 29 17:00:00 PDT 2006
¡Pensé que también lo intentaría hasta que me di cuenta!(aunque buena implementación)