En C # /. NET TimeSpan
tiene TotalDays
, TotalMinutes
etc., pero no puedo encontrar una fórmula para la diferencia total de meses. Los días variables por mes y los años bisiestos no dejan de sorprenderme. ¿Cómo puedo obtener TotalMonths ?
Editar Perdón por no ser más claro: sé que en realidad no puedo obtener esto, TimeSpan
pero pensé usarlo TotalDays
y TotalMinutes
sería un buen ejemplo para expresar lo que estaba buscando ... excepto que estoy tratando de obtener Meses totales.
Ejemplo: 25 de diciembre de 2009 - 6 de octubre de 2009 = 2 meses totales. Del 6 de octubre al 5 de noviembre es igual a 0 meses. El 6 de noviembre, 1 mes. El 6 de diciembre, 2 meses
Respuestas:
No podrá obtener eso de a
TimeSpan
, porque un "mes" es una unidad de medida variable. Tendrás que calcularlo tú mismo, y tendrás que descubrir cómo quieres que funcione exactamente.Por ejemplo, ¿deberían las fechas dar
July 5, 2009
yAugust 4, 2009
producir una diferencia de un mes o cero meses? Si dice que debería producir uno, ¿qué pasa conJuly 31, 2009
yAugust 1, 2009
? ¿ Eso es un mes? ¿Es simplemente la diferencia de losMonth
valores para las fechas, o está más relacionado con un período de tiempo real? La lógica para determinar todas estas reglas no es trivial, por lo que tendrá que determinar las suyas propias e implementar el algoritmo adecuado.Si todo lo que desea es simplemente una diferencia en los meses, sin tener en cuenta los valores de fecha, puede usar esto:
Tenga en cuenta que esto devuelve una diferencia relativa, lo que significa que si
rValue
es mayor quelValue
, entonces el valor de retorno será negativo. Si quieres una diferencia absoluta, puedes usar esto:fuente
(Me doy cuenta de que esta es una vieja pregunta, pero ...)
Esto es relativamente doloroso de hacer en .NET puro. Recomiendo mi propia biblioteca Noda Time , que está especialmente diseñada para cosas como esta:
(Hay otras opciones, p. Ej., Si solo desea un recuento de meses, incluso entre años, lo usaría
Period period = Period.Between(start, end, PeriodUnits.Months);
)fuente
Period.Between
. He editado el código para que funcione con NodaTime 1.3.1.Tal vez no quieras saber sobre fracciones de mes; ¿Qué hay de este código?
fuente
Para comenzar, deberá definir qué quiere decir con TotalMonths.
Una definición simple pone un mes en 30.4 días (365.25 / 12).
Más allá de eso, cualquier definición que incluya fracciones parece inútil, y el valor entero más común (meses enteros entre fechas) también depende de reglas comerciales no estándar.
fuente
He escrito un método de extensión muy simple en
DateTime
yDateTimeOffset
para hacer esto. Quería que funcionara exactamente como funcionaría unaTotalMonths
propiedadTimeSpan
: es decir, devolver el recuento de meses completos entre dos fechas, ignorando cualquier mes parcial. Porque se basa enDateTime.AddMonths()
que respeta diferentes duraciones de mes y devuelve lo que un humano entendería como un período de meses.(Desafortunadamente, no puede implementarlo como un método de extensión en TimeSpan porque eso no retiene el conocimiento de las fechas reales utilizadas, y durante meses son importantes).
El código y las pruebas están disponibles en GitHub . El código es muy simple:
Y pasa todos estos casos de prueba de unidad:
fuente
Necesita resolverlo usted mismo fuera de la fecha y hora. La forma en que lidie con los días de finalización dependerá de para qué quiera usarla.
Un método sería contar el mes y luego corregir por días al final. Algo como:
fuente
Lo haría así:
fuente
return (dtOther.Month - dtThis.Month) + 12 * (dtOther.Year - dtThis.Year);
No hay muchas respuestas claras sobre esto porque siempre estás asumiendo cosas.
Esta solución calcula entre dos fechas los meses transcurridos entre la suposición de que desea guardar el día del mes para la comparación (lo que significa que el día del mes se considera en el cálculo)
Ejemplo, si tiene una fecha del 30 de enero de 2012, el 29 de febrero de 2012 no será un mes, pero el 01 de marzo de 2013 sí.
Se ha probado a fondo, probablemente lo limpiará más tarde a medida que lo usemos, y toma dos fechas en lugar de un intervalo de tiempo, lo que probablemente sea mejor. Espero que esto ayude a alguien más.
fuente
La respuesta aceptada funciona perfectamente cuando quieres meses completos.
Necesitaba meses parciales. Esta es la solución que se me ocurrió durante meses parciales:
También necesitaba un año de diferencia con la misma necesidad de años parciales. Aquí está la solución que se me ocurrió:
fuente
YearDifference
función cuandolValue.Month < rValue.Month
, lo arreglé ahora, es posible que quieras revisar ...Antigua pregunta que conozco, pero podría ayudar a alguien. Utilicé la respuesta aceptada de @Adam arriba, pero luego verifiqué si la diferencia es 1 o -1 y luego verifiqué si es la diferencia de un mes calendario completo. Entonces, 21/07/55 y 20/08/55 no sería un mes completo, pero sí lo sería el 21/07/55 y el 21/07/55.
fuente
fuente
El problema con los meses es que no es realmente una medida simple, no son de tamaño constante. Tendría que definir sus reglas para lo que desea incluir y trabajar desde allí. Por ejemplo, del 1 de enero al 1 de febrero: podría argumentar que hay 2 meses involucrados allí, o podría decir que es un mes. Entonces, ¿qué hay del "1 de enero a las 20:00" hasta el "1 de febrero a las 00:00"? Eso no es todo un mes completo. ¿Eso es 0? 1? ¿Qué pasa al revés (1 enero 00:00 a 1 febrero 20:00) ... 1? 2?
Primero defina las reglas, luego tendrá que codificarlo usted mismo, me temo ...
fuente
Si quieres tener un resultado
1
entre28th Feb
y1st March
:fuente
Esta biblioteca calcula la diferencia de meses, considerando todas las partes de DateTime:
fuente
A continuación se muestra la forma más precisa de hacerlo, ya que la definición de "1 mes" cambia según el mes que sea, ¡y ninguna de las otras respuestas tiene esto en cuenta! Si desea obtener más información sobre el problema que no está integrado en el marco, puede leer esta publicación: Un objeto de intervalo de tiempo real con .Años y meses (sin embargo, leer esa publicación no es necesario para comprender y usar la función a continuación, funciona al 100%, sin las inexactitudes inherentes de la aproximación que a otros les encanta usar, y siéntase libre de reemplazar la función .ReverseIt con la función incorporada .Reverse que puede tener en su marco (está aquí para completar).
Tenga en cuenta que puede obtener cualquier número de fechas / horas de precisión, segundos y minutos, o segundos, minutos y días, en cualquier lugar hasta años (que contendría 6 partes / segmentos). Si especifica los dos primeros y tiene más de un año, devolverá "hace 1 año y 3 meses" y no devolverá el resto porque ha solicitado dos segmentos. si solo tiene unas pocas horas, solo devolverá "hace 2 horas y 1 minuto". Por supuesto, se aplican las mismas reglas si especifica 1, 2, 3, 4, 5 o 6 segmentos (máximo a 6 porque segundos, minutos, horas, días, meses, años solo hacen 6 tipos). También corregirá problemas de gramática como "minutos" vs "minuto" dependiendo de si es 1 minuto o más, lo mismo para todos los tipos, y la "cadena" generada siempre será gramaticalmente correcta.
Estos son algunos ejemplos de uso: bAllowSegments identifica cuántos segmentos mostrar ... es decir: si es 3, entonces la cadena de retorno sería (como ejemplo) ...
"3 years, 2 months and 13 days"
(no incluirá horas, minutos y segundos como los 3 primeros tiempos se devuelven las categorías), si, sin embargo, la fecha era una fecha más reciente, como algo hace unos días, especificando que los mismos segmentos (3) volverán en su"4 days, 1 hour and 13 minutes ago"
lugar, ¡así que tiene todo en cuenta!si bAllowSegments es 2, volvería
"3 years and 2 months"
y si volvería 6 (valor máximo)"3 years, 2 months, 13 days, 13 hours, 29 minutes and 9 seconds"
, pero recuerde que seráNEVER RETURN
algo así,"0 years, 0 months, 0 days, 3 hours, 2 minutes and 13 seconds ago"
ya que entiende que no hay datos de fecha en los 3 segmentos principales y los ignora, incluso si especifica 6 segmentos , así que no te preocupes :). Por supuesto, si hay un segmento con 0, lo tendrá en cuenta al formar la cadena, y se mostrará"3 days and 4 seconds ago"
e ignorará la parte "0 horas". Disfruta y comenta si quieres.Por supuesto, necesitará una función "Reemplazar por última vez", que toma una cadena de origen y un argumento que especifica lo que necesita ser reemplazado, y otro argumento que especifica con qué desea reemplazarlo, y solo reemplaza la última aparición de esa cadena ... He incluido el mío si no tiene uno o no desea implementarlo, por lo que aquí está, funcionará "tal cual" sin necesidad de modificaciones. Sé que la función reverseit ya no es necesaria (existe en .net) pero la función ReplaceLast y ReverseIt se transfieren de los días anteriores a.net, así que disculpe qué tan anticuada puede verse (todavía funciona al 100% aunque em durante más de diez años, puedo garantizar que están libres de errores) ... :). salud.
fuente
Si desea el número exacto, no puede hacerlo solo con el intervalo de tiempo, ya que necesita saber qué meses está tratando y si está tratando con un año bisiesto, como dijo.
Vaya por un número aproximado, o haga un poco de inquietud con los DateTimes originales.
fuente
http://www.astro.uu.nl/~strous/AA/en/reken/juliaansedag.html
Si puede convertir el tiempo de una fecha gregoriana en un número de día juliano , simplemente puede crear un operador para hacer comparaciones del número de día zuliano, que puede ser doble para obtener meses, días, segundos, etc. Consulte lo anterior enlace para un algoritmo para convertir de gregoriano a juliano.
fuente
No hay una forma integrada de hacer esto con precisión en idiomatic-c #. Sin embargo , hay algunas soluciones, como este ejemplo de CodeProject que la gente ha codificado.
fuente
Si se trata de meses y años, necesita algo que sepa cuántos días tiene cada mes y qué años son bisiestos.
Ingrese el calendario gregoriano (y otras implementaciones de calendario específicas de la cultura ).
Si bien Calendar no proporciona métodos para calcular directamente la diferencia entre dos puntos en el tiempo, sí tiene métodos como
fuente
fuente
El método devuelve una lista que contiene 3 elementos: primero es año, segundo es mes y el elemento final es día:
fuente
Aquí está mi contribución para obtener la diferencia en los meses que he encontrado que son precisos:
Uso:
Puede crear otro método llamado DiffYears y aplicar exactamente la misma lógica que anteriormente y AddYears en lugar de AddMonths en el ciclo while.
fuente
Muy tarde al juego, pero imagino que esto puede ser útil para alguien. La mayoría de las personas tienden a medir mes a mes por fecha, excluyendo el hecho de que los meses vienen en diferentes variaciones. Usando ese marco de pensamiento, creé un trazador de líneas que compara las fechas para nosotros. Usando el siguiente proceso.
Si el año final no es mayor, realizamos lo mismo que 2A / 2B, pero sin agregar los 12 meses porque no necesitamos evaluar durante todo el año.
fuente
Mi opinión sobre esta respuesta también utiliza un método de extensión , pero puede devolver un resultado positivo o negativo.
Un par de pruebas:
fuente
Combinando dos de las respuestas anteriores, otro método de extensión es:
Gracias a @AdamRobinson y @MarkWhittaker
fuente
Calcular no de meses entre 2 fechas:
fuente