На каких языках хорошо работают дата, время и календарь? - PullRequest
9 голосов
/ 18 сентября 2008

Вероятно, это слишком много, чтобы спросить, но есть ли какой-нибудь язык, который делает действительно потрясающую работу по представлению операций времени и даты? Сразу признаюсь, что действительно трудно написать действительно великолепную библиотеку времени. Тем не менее, есть ли распространенные языки, которые есть? По сути, я хочу что-то, что обрабатывает время и дату так же полно, как современные библиотеки регулярных выражений выполняют свою работу. Все, что я видел до сих пор в Python и Java, пропускает одну или несколько довольно важных частей или усложняет слишком много вещей.

По крайней мере, это должно быть интуитивно понятно:

  • найти количество дней между двумя указанными датами, количество минут между двумя заданными минутными периодами и т. Д.
  • сложение и вычитание интервалов из отметок времени
  • позволяет простое преобразование между часовыми поясами, при этом автоматически учитывается изменение летнего времени по регионам (учитывая, что имеется точная база данных с региональными настройками)
  • получить период, к которому относится данная временная метка, с учетом детализации периода («в каком календарном дне находится эта дата?»)
  • поддержка очень общих преобразований строки в дату (с учетом шаблона)

Далее, если есть настройка Calendar / GregorianCalendar в стиле Java, общий класс Calendar должен быть приспособлен к подклассам, если мне нужно свернуть свой собственный иврит, вавилонский, толкинский или MartianCalendar. (Java-календари делают это бессмысленно, например.)

Я полностью не зависим от языка. Хорошо, если эта штука захлебнется неоднозначными вещами типа «сколько минут осталось между 2002 и следующим Днем Святого Валентина?»

Ответы [ 15 ]

7 голосов
/ 18 сентября 2008

Как насчет .NET DateTime ? (Вы можете выбрать свой язык в рамках)

4 голосов
/ 18 сентября 2008

Вы ищете что-то вроде PHPs strtotime ? Это даст вам временную метку Unix практически всего, что вы можете в нее добавить.

С php сайта:

<?php
echo strtotime("now"), "\n";
echo strtotime("10 September 2000"), "\n";
echo strtotime("+1 day"), "\n";
echo strtotime("+1 week"), "\n";
echo strtotime("+1 week 2 days 4 hours 2 seconds"), "\n";
echo strtotime("next Thursday"), "\n";
echo strtotime("last Monday"), "\n";
?>

.NET классам даты требуется гораздо больше загадочных манипуляций с DateTimeFormatInfo и т. Д. Для разбора строк дат, которые не так сложны, как strtotime.

PHP предоставляет класс DateTime и класс DateTimeZone начиная с PHP 5, но оба они довольно плохо документированы. Я до сих пор в основном использую метки времени Unix и функции date , time и strtotime , поскольку я не до конца освоился с новыми объектами.

Следующие ссылки пытаются немного улучшить DateTime и DateTimeZone:

3 голосов
/ 18 сентября 2008

Существует действительно классный язык программирования, который называется Frink . Он поддерживает практически все когда-либо изобретенные устройства, каждую физическую или математическую константу, часовые пояса, бла-бла-бла…

Он даже имеет веб-интерфейс и Java-апплет .

Некоторые из ваших вызовов выше:

  • найти количество дней между двумя указанными датами, количество минут между двумя заданными минутными периодами и т. Д.
    • Сколько дней до Рождества: # 2008-12-25 # - now[] -> days
    • Сколько времени прошло с полудня: now[] - # 12:00 # -> minutes
  • сложение и вычитание интервалов из отметок времени
    • Когда у меня был миллион минут рождения: # 1979-01-06 # + 1 million minutes
  • допускает простое преобразование между часовыми поясами, при этом автоматически учитывается изменение летнего времени по регионам (при условии наличия точной базы данных региональных настроек)
    • Когда началась Пекинская Олимпиада в Лондоне: # 2008-08-08 08:08 PM China # -> London
  • поддержка очень общих преобразований строки в дату (с учетом шаблона)
    1. Определить новый формат даты: ### dd.MM.yyyy ###
    2. Разбор: # 18.09.2008 #

Frink прекрасно интегрируется с Java: он может быть встроенным в приложения Java , а программы Frink могут вызывать код Java .

3 голосов
/ 18 сентября 2008

Возможно, вы захотите проверить модуль Date :: Manip Perl в CPAN.

3 голосов
/ 18 сентября 2008

Для Java я настоятельно рекомендую библиотеку Joda Date / Time .

2 голосов
/ 18 сентября 2008

Для C ++ есть Boost.Date_Time .

2 голосов
/ 18 сентября 2008

PHP не наполовину плох.

// given two timestamps: $t1, and $t2:

// find the number of days between two given dates, number of minutes
// between two given minute periods, etc.  
$daysBetween = floor(($t2 - $t1) / 86400);  // 86400 = 1 day in seconds
$hoursBetween = floor(($t2 - $t1) / 3600);  // 3600 = 1 hour in seconds

// add and subtract intervals from timestamps  
$newDate = $t1 + $interval;

// allow simple conversion between timezones, with Daylight Saving Time
// changes by region automatically accounted for (given that there's an
// accurate supporting database of regional settings available)

// See PHP's Calendar functions for that
// http://au2.php.net/manual/en/book.calendar.php
// It not only supports basic stuff like timezones and DST, but also
// different types of calendar: French, Julian, Gregorian and Jewish.

// get the period that a given timestamp falls into, given period
// granularity ("what calendar day is this date in?")  
if (date("d", $t1) == 5)    // check if the timestamp is the 5th of the month
if (date("h", $t1) == 16)   // is it 4:00pm-4:59pm ?

// support very general string-to-date conversions (given a pattern) 

// strtotime() is magic for this. you can just type in regular english
// and it figures it out. If your dates are stored in a particular format
// and you want to convert them, you can use strptime()

Вы должны отдать ему должное за то, что у есть функция, чтобы сказать, какая дата Пасхи в данном году .

2 голосов
/ 18 сентября 2008

Мне нравится .NET для этого. Он обеспечивает хорошие манипуляции с датой / временем, с классами DateTime и Timespan. Тем не менее, большинство материалов с датой и временем довольно просты на любом языке, что даст вам метку времени Unix для работы.

1 голос
/ 13 апреля 2019

java.time

Ведущая в отрасли инфраструктура даты и времени: java.time , встроенная в Java 8 и более поздние версии, определяемая как JSR 310 .

Человек, ведущий этот проект - Стивен Коулборн . Он также возглавлял своего предшественника, очень успешный проект Joda-Time . Уроки, извлеченные с Joda-Time , были применены при разработке совершенно новых java.time классов. Кстати, Joda-Time был портирован на .Net в проекте NodaTime .

найдите количество дней между двумя указанными датами,

Используйте класс Period для представления промежутка времени в гранулированности лет-месяцев-дней.

LocalDate start = LocalDate.of( 2019 , Month.JANUARY , 23 ) ;
LocalDate stop = LocalDate.of( 2019 , Month.MARCH , 3 ) ;
Period p = Period.between( start , stop ) ;

Или, если вы хотите просто указать общее количество дней, используйте ChronoUnit.

long days = ChronoUnit.DAYS.between( start , stop ) ;

количество минут между двумя заданными минутными периодами и т. Д.

Используйте класс Duration для представления промежутка времени с детализацией дней (24-часовой период времени, не связанный с календарем), часов, минут, секунд, доли секунды.

Instant start = Instant.now() ;    // Capture the current moment as seen in UTC.
…
Instant stop = Instant.now() ;
Duration d = Duration.between( start , stop ) ;

Если вы хотите, чтобы общее количество минут истекло за весь промежуток времени, позвоните по номеру toMinutes.

long elapsedMinutes = d.toMinutes() ;

сложение и вычитание интервалов из отметок времени

Вы можете выполнять математику даты и времени, используя классы Period и Duration, упомянутые выше, передавая методы plus & minus в различных классах.

Instant now = Instant.now() ;
Duration d = Duration.ofMinutes( 7 ) ;
Instant later = now.plus( d ) ;

позволяет простое преобразование часовых поясов, при этом изменения летнего времени по регионам автоматически учитываются

Класс ZoneId хранит историю прошлых, настоящих и будущих изменений смещения, используемого людьми определенного региона, то есть часового пояса.

Укажите правильное имя часового пояса в формате Continent/Region, например America/Montreal, Africa/Casablanca или Pacific/Auckland. Никогда не используйте 2-4-буквенное сокращение, например EST или IST, так как они не истинных часовых поясов, не стандартизированы и даже не уникальны (!).

ZoneId z = ZoneId.of( "America/Montreal" ) ;  
LocalDate today = LocalDate.now( z ) ;        // Get the current date as seen by the people of a certain region. 

Если вы хотите использовать текущий часовой пояс JVM по умолчанию, запросите его и передайте в качестве аргумента. Если опущен, код становится неоднозначным для чтения, поскольку мы точно не знаем, намеревались ли вы использовать значение по умолчанию или если вы, как и многие программисты, не знали об этой проблеме.

ZoneId z = ZoneId.systemDefault() ;  // Get JVM’s current default time zone.

Мы можем использовать ZoneId для настройки между зонами. Во-первых, давайте посмотрим на текущий момент в формате UTC.

Instant instant = Instant.now() ;

Применение часового пояса к часовому поясу в Тунисе. Примените ZoneId к Instant, чтобы получить объект ZonedDateTime. Тот же момент, та же точка на временной шкале, но другое время на настенных часах.

ZoneId zTunis = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdtTunis = instant.atZone( zTunis ) ;

Давайте посмотрим в тот же момент, что и в Японии, который смотрит на часы на своей стене.

ZoneId zTokyo = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdtTokyo = zdtTunis.withZoneSameInstant( zTokyo ) ;  // Same moment, different wall-clock time.

Все три объекта, instant, zdtTunis и zdtTokyo, представляют один и тот же момент. Представьте себе трехстороннюю телефонную конференцию между кем-то в Исландии (где они используют UTC), кем-то в Тунисе и кем-то в Японии. Если каждый человек в один и тот же момент смотрит на часы и календарь на соответствующей стене, каждый из них увидит на своих часах разное время суток и, возможно, другую дату в своем календаре.

Обратите внимание, что java.time использует неизменных объектов . Вместо того, чтобы изменять («изменять») объект, возвращайте новый новый объект на основе значений оригинала.

(учитывая, что имеется точная база данных поддержки региональных настроек)

Java включает в себя копию tzdata , базы данных стандартного часового пояса. Убедитесь, что ваша JVM обновлена, чтобы соответствовать текущим определениям часовых поясов. К сожалению, политики во всем мире проявляют склонность к пересмотру часовых поясов своей юрисдикции практически без предварительного предупреждения. Поэтому вам может потребоваться обновить tzddata вручную, если часовой пояс, о котором вы беспокоитесь, внезапно изменится.

ПоКстати, ваша операционная система, скорее всего, также имеет собственную копию tzdata . Держите это свежим для ваших потребностей не-Java. То же самое для любых других систем, которые вы могли установить, таких как сервер баз данных, например Postgres с собственной копией tzdata .

получить период, в который попадает данная временная метка, с учетом детализации периода («в каком календарном дне находится эта дата?»)

Под «календарным днем» вы подразумеваете день недели? В java.time у нас есть DayOfWeek enum, который предопределяет семь объектов, по одному на каждый день недели.

DayOfWeek dow = LocalDate.now( z ).getDayOfWeek() ;

Под «календарным днем» вы подразумеваете день года (1-366)?

int dayOfYear = LocalDate.now( z ).getDayOfYear() ;

Под «календарным днем» вы подразумеваете представление год-месяц ?

YearMonth ym = YearMonth.from( today ) ;  // `today` being `LocalDate.now( ZoneId.of( "Pacific/Auckland" ) )`. 

Возможно, месяц-день?

MonthDay md = MonthDay.from( today ) ;

поддержка очень общих преобразований строки в дату (с учетом шаблона)

Вы можете указать пользовательский шаблон форматирования, который будет использоваться при разборе / генерации строки, представляющей значение объекта даты и времени. Смотрите метод DateTimeFormatter.ofPattern. Поиск переполнения стека для получения дополнительной информации, так как это было обработано много раз.

Если ваша строка правильно отформатирована в соответствии с правилами локализации для конкретной культуры, вы можете позволить java.time выполнить синтаксический анализ, не удосуживаясь определить шаблон форматирования.

Locale locale = Locale.CANADA_FRENCH ; 
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( FormatStyle.MEDIUM ).withLocale( locale ) ;
String output = LocalDate.now( z ).format( f ) ; 

если есть настройка календаря / GregorianCalendar в стиле Java

Классы Calendar и GregorianCalendar, включенные в ранние версии Java, ужасны. Никогда не используйте их. Они полностью вытесняются классами java.time , в частности классом ZonedDateTime.

приспосабливаясь к подклассам, если мне нужно свернуть свой собственный иврит, вавилонский, толкинский или марсианский календарь. (Java-календари делают это бессмысленно, например.)

Многие системы календаря уже были внедрены для java.time . Каждый из них известен как хронология . Календарная система, обычно используемая на Западе и во многих сферах бизнеса по всему миру, представляет собой хронологию ISO 8601 . Это используется по умолчанию в java.time , java.time.chrono.IsoChronology.

В комплекте с Java вы также найдете дополнительные хронологии, включая версию исламского календаря хиджра , систему календаря японской империи, систему календаря Minguo (Тайвань и т. Д.) И Тайский буддистский календарь.

Вы найдете больше хронологий, определенных в проекте ThreeTen-Extra . См. Пакет org.threeten.extra.chrono для получения списка, включающего: стандартный бухгалтерский календарь IRS / IFRS, британский юлиан-григорианский календарный календарь, коптский христианский календарь, систему Discordian календаря, эфиопский календарь, международный фиксированный календарь (календарь Eastman Kodak) , юлианский календарь и многое другое.

Но если вам нужен какой-то другой календарь, java.time предоставляет AbstractChronology, чтобы начать работу. Но сделайте серьезный поиск в Интернете, прежде чем начинать самостоятельно, так как он уже может быть построен. И все перечисленные выше хронологии с открытым исходным кодом, так что вы можете изучить их для руководства.

"Сколько минут у вас между 2002 и следующим Днем Святого Валентина?"

LocalDate date2002 = Year.of( 2002 ).atDay( 1 );

MonthDay valentinesHoliday = MonthDay.of( Month.FEBRUARY , 14 );

ZoneId z = ZoneId.of( "America/Edmonton" );
LocalDate today = LocalDate.now( z );
LocalDate valDayThisYear = today.with( valentinesHoliday );
LocalDate nextValDay = valDayThisYear;
if ( valDayThisYear.isBefore( today ) )
{ // If Valentine's day already happened this year, move to next year’s Valentine's Day.
    nextValDay = valDayThisYear.plusYears( 1 );
}

ZonedDateTime start = date2002.atStartOfDay( z );
ZonedDateTime stop = nextValDay.atStartOfDay( z );
Duration d = Duration.between( start , stop );
long minutes = d.toMinutes();

System.out.println( "From start: " + start + " to stop: " + stop + " is duration: " + d + " or a total in minutes: " + minutes + "." );
LocalDate date2002 = Year.of( 2002 ).atDay( 1 );

MonthDay valentinesHoliday = MonthDay.of( Month.FEBRUARY , 14 );

ZoneId z = ZoneId.of( "America/Edmonton" );
LocalDate today = LocalDate.now( z );
LocalDate valDayThisYear = today.with( valentinesHoliday );
LocalDate nextValDay = valDayThisYear;
if ( valDayThisYear.isBefore( today ) )
{ // If Valentine's day already happened this year, move to next year’s Valentine's Day.
    nextValDay = valDayThisYear.plusYears( 1 );
}

ZonedDateTime start = date2002.atStartOfDay( z );
ZonedDateTime stop = nextValDay.atStartOfDay( z );
Duration d = Duration.between( start , stop );
long minutes = d.toMinutes();

System.out.println( "From start: " + start + " to stop: " + stop + " is duration: " + d + " or a total in minutes: " + minutes + "." );

При запуске.

С начала: 2002-01-01T00: 00-07: 00 [Америка / Эдмонтон] до остановки: 2020-02-14T00: 00-07: 00 [Америка / Эдмонтон]: продолжительность: PT158832H или общее количество минут : 9529920.


О java.time

Фреймворк java.time встроен в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

на выходБолее подробно см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .

Вы можете обмениваться java.time объектами напрямую с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где взять классы java.time?

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval, YearWeek, YearQuarter и more .

1 голос
/ 05 марта 2009

Функция PHP Date является фантастической и имеет множество полезных функций (ссылка: php.net / date )

.NET неплох в своих последних выпусках, плюс мне нравится тот факт, что вы можете добавить ссылку на дополнительный язык и смешать и сопоставить код в вашем проекте. Таким образом, вы можете использовать функции C # и VB в одном классе.

...