Каков наиболее эффективный способ преобразования восьмизначного числа в дату?

Я использую ColdFusion 9.0.1 и некоторую базу данных, которую я не могу изменить.

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

YYYYMMDD

Мне нужно иметь возможность читать дату, добавлять и вычитать дни из даты и создавать новые даты. Я ищу решение ColdFusion для эффективного (не много кода) преобразования даты в наш стандартный формат, который

MM/DD/YYYY

А затем преобразовать его обратно в формат базы данных для сохранения.

Мне нужно закодировать это таким образом, чтобы программисты, не работающие с ColdFusion, могли легко прочитать это и использовать, копировать и изменять для других функций (например, для добавления дня к дате). Итак, я ищу не самый минимум кода, а эффективный и читаемый код.

Можете ли вы предложить что-нибудь, что сделало бы этот блок кода более гибким, удобочитаемым или более эффективным (меньше кода)?

<cfscript>

// FORMAT DB DATE FOR BROWSER
DateFromDB = "20111116";
DatedToBrowser = createBrowserDate(DateFromDB);
writeOutput(DatedToBrowser);

function createBrowserDate(ThisDate) {
    ThisYear = left(ThisDate, 4); 
    ThisMonth = mid(ThisDate, 4, 2);
    ThisDay = right(ThisDate, 2);
    NewDate = createDate(ThisYear, ThisMonth, ThisDay);
    NewDate = dateFormat(NewDate, "MM/DD/YYYY");
    return NewDate;
}

// FORMAT BROWSER DATE FOR DB
DateFromBrowser = "11/16/2011";
DateToDB = createDBDate(DateFromBrowser);
writeDump(DateToDB);

function createDBDate(ThisDate) {
    ThisYear = year(ThisDate); 
    ThisMonth = month(ThisDate);
    ThisDay = day(ThisDate);
    NewDate = "#ThisYear##ThisMonth##ThisDay#";
    return NewDate;
}

</cfscript>

person Evik James    schedule 16.11.2011    source источник
comment
Я думаю, что это вполне читабельно прямо сейчас, просто не забудьте использовать переменные Var в этих функциях.   -  person Henry    schedule 16.11.2011
comment
Будучи придирчивым здесь... Я бы изменил NewDate = #ThisYear##ThisMonth##ThisDay#; to NewDate = ThisYear&ThisMonth&ThisDay, но я ненавижу посторонние хеш-теги в своем коде. Кроме того, вы можете избавиться от createdate() и dateFormat() в 1-й функции и просто вернуть thisMonth & / & Thisday & / & ThisYear;   -  person Scott Stroz    schedule 16.11.2011
comment
На самом деле... взглянув на это еще раз, вы можете изменить createDBDate, чтобы просто возвращать dateFormat(ThisDate, YYYYMMDD)   -  person Scott Stroz    schedule 16.11.2011


Ответы (5)


Фактически вы можете переписать каждую функцию в 1 строку кода.

function createBrowserDate(ThisDate) {
  return mid(ThisDate,4,2) & "/" & right(ThisDate,2) & "/" & left(ThisDate,4);
}

и

function createDBDate(ThisDate) {
  return dateFormat( ThisDate, "YYYYMMDD" );
}
person Scott Stroz    schedule 16.11.2011
comment
Я думаю, что вы, возможно, немного сжали его для моих целей, но он, безусловно, наиболее удобочитаемый с наименьшим количеством кода. Спасибо! - person Evik James; 17.11.2011
comment
Это может иметь наименьший код, но без createDate() вы пропускаете проверку. Во-вторых, ThisDate здесь означает две разные вещи, поскольку 1-й ожидает ГГГГММДД, а 2-й ожидает объект Date. Наконец, вы не можете использовать встроенные функции даты CF только с этими двумя функциями. - person Henry; 17.11.2011
comment
Во-первых, даже с createDate() нет «проверки», если значение, переданное в createBrowserDate(), не является действительной датой, createDate() выдаст ошибку. Во-вторых, какое значение имеет, если «ThisDate» является именем аргумента в двух разных функциях? Наконец, почему вы не можете использовать какие-либо встроенные функции даты? - person Scott Stroz; 18.11.2011

Сначала найди, кто когда-либо занимался базой данных, и надери им задницу...

Лично я конвертировал с помощью sql, поэтому мой код имел дело только с объектами даты.

Select Convert(DateTime, Convert(VarChar(8),DateTimeInventedByIdjitColumn))
From SomeTable

Как утверждают наши коллеги, храните даты как даты.

«06.08.2011» может быть 8 июня или 6 августа в зависимости от региона.

20111643 — допустимое целое число.

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

person Tony Hopkinson    schedule 16.11.2011
comment
хорошая точка зрения! хотя вопрос не в этом. А поскольку формат даты БД — YYYYMMDD, он, по крайней мере, поддается сортировке, а YYYYDDMM редко используется где-либо еще, поэтому ошибиться не так просто. - person Henry; 16.11.2011
comment
Если вы вынуждены использовать строковый формат для дат, лучше всего использовать ГГГГММДД, но это не означает, что даты должны храниться в виде строк. - person Peter Boughton; 17.11.2011
comment
Преобразование на этапе SQL, безусловно, является хорошей идеей и имеет больше смысла, чем выполнение этого с помощью функции CFML, хотя я думаю, что пример кода здесь предполагает MS SQL Server? Это важно отметить, поскольку разные платформы имеют разные функции преобразования, и мы не знаем, какую из них использует OP. - person Peter Boughton; 17.11.2011
comment
Запястье крепко ударило по синтаксису sql, я упомяну, какой из них я использую с этого момента. Мы склонны использовать ГГГГ-ММ-ДД, что одинаково универсально. Не могу использовать целое число, а не будущее, когда оно переполняется (усмехается) - person Tony Hopkinson; 17.11.2011
comment
Питер, ты сделал отличное замечание. Причина, по которой я запрашиваю решение ColdFusion, заключается в том, что я не знаю используемую базу данных. На самом деле, другие разработчики даже не знают. Это своего рода большая загадка. Моя работа заключается в том, чтобы создавать решения ColdFusion для этих небольших проблем. - person Evik James; 17.11.2011
comment
Неиспользование правильного типа даты — это просто огромный набор функций и ошибок, которые в лучшем случае ждут своего появления. ~ это мягко сказано. Вы не поверите, какие препятствия нам приходится преодолевать, чтобы наш сайт общался с этой базой данных. Там мало последовательности, чтобы быть найденным. Спасибо за цитату! - person Evik James; 17.11.2011

Не храните даты в виде строк. Сохраняйте даты как даты и форматируйте их при необходимости.

Если вы не можете исправить базу данных для использования фактических столбцов даты (что вы должны, если можете), вы можете использовать эти две функции для преобразования в/из ГГГГММДД и объекта даты:

function parseYMD( YYYYMMDD )
{
    if ( ! refind('^\d{8}$' , Arguments.YYYYMMDD ) )
        throw "Invalid Format. Expected YYYYMMDD";

    return parseDateTime
        ( Arguments.YYYYMMDD.replaceAll('(?<=^\d{4})|(?=\d{2}$)','-') );
}

function formatYMD( DateObj )
{
    return DateFormat( DateObj , 'yyyymmdd' );
}


Использование объектов даты означает, что разработчик любого уровня может работать с ними, не заботясь о форматировании, с помощью встроенных функций, таких как Добавление даты, Сравнение даты и т. д.

person Peter Boughton    schedule 16.11.2011
comment
Я мог бы использовать throw(), а не throw, чтобы я мог создать лучший тип исключения, чем просто приложение, но в остальном я думаю, что это лучший ответ здесь. - person Adam Cameron; 17.11.2011
comment
Питер, я очень ценю, что ты нашел время, чтобы ответить на вопрос. Тем не менее, я не думаю, что вы внимательно прочитали мой вопрос. Во-первых, у меня нет контроля над базой данных. Я не могу ничего изменить и посоветовать что-либо изменить. Во-вторых, хотя ваш код может выполняться идеально, он далеко не читается обычным программистом (кем бы он ни был). Спасибо! - person Evik James; 17.11.2011
comment
Для протокола: я специально спросил каждого из людей, с которыми я работаю, об их опыте работы с регулярными выражениями. Ни у кого не было опыта. Самым большим преимуществом использования ColdFusion является наличие 100 решений любой проблемы. Спасибо за Ваш ответ! - person Evik James; 17.11.2011

Я не фанат регулярных выражений, так как они не очень понятны для меня.

Поскольку вы используете CF9, я набрал аргумент и указал возвращаемый тип функций, чтобы сделать его еще более читаемым для следующего человека, который возьмет ваш код.

Во-первых, сразу после того, как я прочитал дату из БД, я бы разобрал ее на объект Date, используя parseDBDate()

Date function parseDBDate(required String dbDate)
{
    var yyyy = left(dbDate, 4); 
    var mm = mid(dbDate, 4, 2);
    var dd = right(dbDate, 2);

    return createDate(yyyy , mm, dd);
}

Когда у вас есть объект даты, вы можете использовать все эти встроенные функции даты, такие как DateAdd() или DateDiff().

Вызовите browserDateFormat() прямо перед тем, как вам нужно отобразить его.

String function browserDateFormat(required Date date) 
{
    return dateFormat(date, "MM/DD/YYYY");
}

Вызовите dBDateFormat() внутри <cfqueryparam value="">, когда пришло время сохраниться в БД

String function dBDateFormat(required Date date) 
{
    return dateFormat(date, "YYYYMMDD");
}
person Henry    schedule 16.11.2011
comment
FWIW, мое регулярное выражение в основном говорит, что в позиции после первых четырех цифр или позиции перед двумя последними цифрами вставьте дефис. Regex действительно несложно изучить, если вы потратите некоторое время на его понимание. :) - person Peter Boughton; 17.11.2011
comment
Спасибо за информацию! Похоже, вы пришли из мира Java. Истинный? - person Evik James; 17.11.2011
comment
Вроде. :) Просто следуя соглашению об именах функций CF с parseXXX() и XXXFormat() - person Henry; 17.11.2011

Один лайнер :)

myDateString = "20110203";

myCfDate = createObject("java","java.text.SimpleDateFormat").init("yyyyMMdd").parse(myDateString,createObject("java","java.text.ParsePosition").init(0*0));

Если вы хотите анализировать другие шаблоны, измените «ггггММдд» на любой другой поддерживаемый шаблон.

http://download.oracle.com/javase/1.5.0/docs/api/java/text/SimpleDateFormat.html

ParsePosition используется, чтобы указать, с чего начать синтаксический анализ строки. 0*0 является сокращением для JavaCast("int",0) - в движке Adobe cf 0 - это строка, пока вы не примените к ней математику, тогда она станет Double, которую поддерживает конструктор ParsePosition. Технически он конструируется с помощью int, но cf достаточно умен, чтобы понизить Double до int.

http://download.oracle.com/javase/1.5.0/docs/api/java/text/ParsePosition.html

person Mike Causer    schedule 18.11.2011