Una forma de pensar sobre esto es a qué te refieres con hora / fecha ? Las computadoras no saben cuáles son estos conceptos: tienen que ser programados de alguna manera. Es bastante común representar veces en el formato UNIX de "segundos desde la época", y es común introducir un valor particular en un programa a través de llamadas del sistema operativo. Sin embargo, no importa cuán común sea este uso, es importante tener en cuenta que no es el momento "real": es solo una representación lógica.
Como han señalado otros, si creó un "plazo límite" utilizando este mecanismo, es trivial alimentar en un momento diferente y romper ese "plazo límite". Lo mismo ocurre con mecanismos más elaborados, como solicitar un servidor NTP (incluso a través de una conexión "segura", ya que podemos sustituir nuestros propios certificados, autoridades de certificados o incluso parchar las bibliotecas criptográficas). Al principio, puede parecer que estas personas tienen la culpa de trabajar en torno a su mecanismo, pero puede darse el caso de que se haga automáticamente y por buenas razones . Por ejemplo, es una buena idea tener compilaciones reproducibles , y las herramientas para ayudar a esto podrían restablecer / interceptar automáticamente tales llamadas de sistema no deterministas. libfaketime hace exactamente eso, Nix establece todo las marcas de tiempo del archivo a 1970-01-01 00:00:01
, función de grabación / reproducción de Qemu hace que toda la interacción de hardware, etc. .
Esto es similar a ley de Goodhart : si la conducta de un programa depende de la hora lógica, entonces el tiempo lógico deja de ser una buena medida del tiempo "real". En otras palabras, la gente generalmente no se mete con el reloj del sistema, pero lo hará si le das una razón para hacerlo.
Hay otras representaciones lógicas del tiempo: una de ellas es la versión del software (ya sea su aplicación o alguna dependencia). Esta es una representación más deseable para una "fecha límite" que, por ejemplo, El tiempo de UNIX, ya que es más específico para lo que le interesa (cambiar los conjuntos de funciones / API) y, por lo tanto, es menos probable que pisotee los problemas ortogonales (por ejemplo, jugar con el tiempo de UNIX para solucionar su fecha límite podría terminar rompiendo los archivos de registro y los trabajos cron , cachés, etc.).
Como han dicho otros, si controla la biblioteca y desea "impulsar" este cambio, puede impulsar una nueva versión que desaprueba las características (lo que provoca advertencias, para ayudar a los consumidores a encontrar y actualizar su uso), y luego otra nueva versión lo que elimina las características por completo. Puede publicarlos inmediatamente uno tras otro si lo desea, ya que (nuevamente) las versiones son simplemente una representación lógica del tiempo, no es necesario que estén relacionadas con el tiempo "real". Las versiones semánticas pueden ayudar aquí.
El modelo alternativo es "arrastrar" el cambio. Esto es como su "plan B": agregue una prueba a la aplicación consumidora, que comprueba que la versión de esta dependencia es al menos el nuevo valor. Como de costumbre, rojo / verde / refactor para propagar este cambio a través del código base. Esto puede ser más apropiado si la funcionalidad no es "mala" o "incorrecta", sino simplemente "una mala adaptación para este caso de uso".
Una pregunta importante con el enfoque "pull" es si la versión de dependencia cuenta como una "unidad" ( de funcionalidad ), y por lo tanto merece ser probado; o si es solo un detalle de implementación "privada", que solo debe ejercerse como parte de la unidad real ( de funcionalidad ) pruebas. Yo diría: si la distinción entre las versiones de la dependencia realmente cuenta como una característica de su aplicación, entonces haga la prueba (por ejemplo, verificando que la versión de Python es > = 3.x). Si no, entonces no agregue la prueba (ya que será frágil, poco informativa y demasiado restrictiva); Si controla la biblioteca, vaya por la ruta "push". Si no controla la biblioteca, simplemente use la versión que se proporciona: si sus pruebas pasan, entonces no vale la pena restringirse; si no se aprueban, ¡ese es tu "plazo" justo allí!
Hay otro enfoque, si desea desalentar ciertos usos de las características de una dependencia (por ejemplo, llamar a ciertas funciones que no funcionan bien con el resto de su código), especialmente si no controla la dependencia: tenga su los estándares de codificación prohíben / desalientan el uso de estas funciones y agregan comprobaciones a su indicador.
Cada uno de estos será aplicable en diferentes circunstancias.