У меня есть дни рождения всех пользователей, сохраненные как UNIXtimestamp, и желаю отослать электронные письма каждый день пользователям, которые имеют день рождения в тот день.
Я должен сделать запрос MySQL, который получит все строки, которые содержат день рождения в сегодняшнюю дату.
Кажется, что это должно быть довольно просто, но возможно я просто сверхусложняю его.
Это должно сработать:
SELECT *
FROM USERS
WHERE
DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') = DATE_FORMAT(NOW(),'%m-%d')
Вот ответ, в котором свойство учитывает високосные годы и всегда будет выдавать вам пользователей, чей день рождения приходится на 29 февраля одновременно с 1 марта.
SELECT *
FROM USERS
WHERE
DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') = DATE_FORMAT(NOW(),'%m-%d')
OR (
(
DATE_FORMAT(NOW(),'%Y') % 4 <> 0
OR (
DATE_FORMAT(NOW(),'%Y') % 100 = 0
AND DATE_FORMAT(NOW(),'%Y') % 400 <> 0
)
)
AND DATE_FORMAT(NOW(),'%m-%d') = '03-01'
AND DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') = '02-29'
)
Вы просто хотите писать, верно? Это сериализованный массив или синтаксический анализ?
Одним из способов чтения конфигурационного файла является parse _ ini _ file () . Я бы не стал называть это предпочтительным, но это метод. Тебе все еще нужно написать файл.
Другим способом было бы написать «config.inc.php» и просто включить его в, чтобы записать его вы просто вывести фактический PHP код (например, $ var = «myval»;).
Таким образом можно записать простую «выходную» функцию, которая взяла массив значений конфигурации и вывела их как имя = значение, предполагая, что $ config был ассоциативным массивом.
foreach ($config as $name => $value) {
$output .= $name . '=' . $value . "\n";
}
if (!file_put_contents($filename, $output)) {
die("Error writing config file.");
}
Есть много достойных способов сделать это. Это действительно основано на ваших требованиях. Нужно ли иметь в определенном формате или у вас есть свобода действий?
-121--4518411-Допустим, файл config.inc выглядит следующим образом:
$config = array(
'blah' => 'mmm',
'blah2' => 'www',
//...
);
Вы хотите обновить его, чтобы создать простую форму, заполнить текстовые поля текущими значениями. Сценарий PHP, перезаписывающий текущую конфигурацию, может выглядеть следующим образом:
$newConfig = ...; // data from form - of course validate it first
$config = ...; // data from config.inc
$config = array_merge($config, $newConfig);
file_put_contents('config.inc', '<?php $config = ' . var_export($config, true));
И вы закончили.
-121--4518418-Я взял ответ Сагги Малахи и расширил его, включив день рождения 29 февраля в дату 28 февраля, если в этом году такого дня нет.
SELECT *
FROM USERS
WHERE
DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') = DATE_FORMAT(NOW(),'%m-%d')
UNION
SELECT *
FROM USERS
WHERE
DATE_FORMAT(NOW(),'%Y')%4 != 0 AND DATE_FORMAT(NOW(),'%m-%d')='02-28' and DATE_FORMAT(FROM_UNIXTIME(birthDate),'%m-%d') = '02-29'
Поскольку это все больше и больше становится вопросом кода-гольфа, вот мой подход к его решению, включая забота о високосных годах:
select *
from user
where (date_format(from_unixtime(birthday),"%m-%d") = date_format(now(),"%m-%d"))
or (date_format(from_unixtime(birthday),"%m-%d") = '02-29'
and date_format('%m') = '02'
and last_day(now()) = date(now())
);
Объяснение: Первое предложение where проверяет, наступил ли чей-то день рождения сегодня. Второе гарантирует, что выбраны только те, чей день рождения 29 февраля, только если текущий день равен последнему день февраля.
Примеры:
SELECT last_day('2009-02-01'); -- gives '2009-02-28'
SELECT last_day('2000-02-01'); -- gives '2009-02-29'
SELECT last_day('2100-02-01'); -- gives '2100-02-28'
set @now=now();
select * from user where (month(birthday) = month(@now) and day(birthday) = day(@now)) or
(month(birthday) = 2 and day(birthday) = 29 and month(@now) = 2 and day(@now) = 28 and
month(date_add(@now, interval 1 day)) = 3);
Не могли бы вы просто выбрать все строки, соответствующие дате текущего дня? Вы также можете использовать функцию FROM_UNIXTIME () для преобразования метки времени unix в дату:
mysql> SELECT FROM_UNIXTIME (1196440219); -> '2007-11-30 10:30:19'
Это описано в http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_from-unixtime
Более полный ответ:
class MyClass(object):
def __init__(self):
self.numbers = [1,2,3,4,54]
def __contains__(self, key):
return key in self.numbers
Здесь вы получите True, когда спросите, был ли 54 в m:
>>> m = MyClass()
>>> 54 in m
True
См. документацию по перегрузке __ содержит __
.
Я обнаружил, что лучшим способом решения этой проблемы является использование < label >
и размещение его над областью ввода. Это дает вам:
Вот версия ванили, так как вы не просили фреймворк. Разметка не должна изменяться, но может потребоваться настройка CSS для удовлетворения ваших потребностей.
HTML:
<html>
<head>
<style>
label.magiclabel {
position: absolute;
padding: 2px;
}
label.magiclabel,
input.magiclabel {
width: 250px;
}
.hidden { display: none; }
</style>
<noscript>
<style>
/* Example of graceful degredation */
label.magiclabel {
position: static;
}
</style>
</noscript>
</head>
<body>
<label>This is not a magic label</label>
<form>
<label class="magiclabel" for="input-1">Test input 1</label>
<input class="magiclabel" type="text" id="input-1" name="input_1" value="">
<label class="magiclabel" for="input-2">Test input 2 (with default value)</label>
<input class="magiclabel" type="text" id="input-2" name="input_2" value="Default value">
</form>
<script src="magiclabel.js"></script>
</body>
</html>
vanilla-magiclabel.js
(function() {
var oldOnload = typeof window.onload == "function" ? window.onload : function() {};
window.onload = function() {
// Don't overwrite the old onload event, that's just rude
oldOnload();
var labels = document.getElementsByTagName("label");
for ( var i in labels ) {
if (
// Not a real part of the container
!labels.hasOwnProperty(i) ||
// Not marked as a magic label
!labels[i].className.match(/\bmagiclabel\b/i) ||
// Doesn't have an associated element
!labels[i].getAttribute("for")
) { continue; }
var associated = document.getElementById( labels[i].getAttribute("for") );
if ( associated ) {
new MagicLabel(labels[i], associated);
}
}
};
})();
var MagicLabel = function(label, input) {
this.label = label;
this.input = input;
this.hide = function() {
this.label.className += " hidden";
};
this.show = function() {
this.label.className = this.label.className.replace(/\bhidden\b/ig, "");
};
// If the field has something in it already, hide the label
if ( this.input.value ) {
this.hide();
}
var self = this;
// Hide label when input receives focuse
this.input.onfocus = function() {
self.hide();
};
// Show label when input loses focus and doesn't have a value
this.input.onblur = function() {
if ( self.input.value === "" ) {
self.show();
}
};
// Clicking on the label should cause input to be focused on since the `for`
// attribute is defined. This is just a safe guard for non-compliant browsers.
this.label.onclick = function() {
self.hide();
};
};
Как вы видите, около половины кода завернуто в инициализации в window.onload
. Это можно смягчить с помощью структуры. Вот версия с использованием jQuery:
$(function() {
$("label.magiclabel[for]").each(function(index, label) {
label = $(label);
var associated = $("#" + label.attr("for"));
if ( associated.length ) {
new MagicLabel(label, associated);
}
});
});
var MagicLabel = function(label, input) {
// If the field has something in it already, hide the label
if ( input.val() !== "" ) {
label.addClass("hidden");
}
label.click(function() { label.addClass("hidden"); });
input.focus(function() { label.addClass("hidden"); });
input.blur(function() {
if ( input.val() === "" ) {
label.removeClass("hidden");
}
});
};
демонстрация jQuery . Разметку не нужно изменять, но, конечно, необходимо включить библиотеку jQuery.
-121--4213438-Приведенный ниже ответ на самом деле не работает. При этом не учитывается тот факт, что год составляет 365,24 (високосные дни то и дело) дня, поэтому фактическое сравнение с датой рождения пользователей, по меньшей мере, сложно. Я оставляю его по историческим причинам.
Другие ответы должны работать, но если вы хотите небольшую оптимизацию, скажем, если есть много много строк, вам, вероятно, лучше выразить запрос непосредственно в секундах временной метки. Можно использовать уравнения (немного задействованные из-за учета часового пояса):
today _ starts = UNIX_TIMESTAMP (NOW ()) - TIMESTAMPDIFF (SECOND, DATE (NOW ()), NOW ()) today_ends = today_starts + 86400
и затем выберите записи, в которых отметка времени находится между этими значениями.
Вот мой вклад
SELECT
DAYOFYEAR(CURRENT_DATE)-(dayofyear(date_format(CURRENT_DATE,'%Y-03-01'))-60)=
DAYOFYEAR(the_birthday)-(dayofyear(date_format(the_birthday,'%Y-03-01'))-60)
FROM
the_table
Биты '(dayofyear(date_format(current_date,'%Y-03-01'))-60)' возвращают 1 в високосные годы, так как 1 марта будет день года номер 61, и 0 в обычные годы.
Отсюда остается только вычесть этот дополнительный день из расчета "is-it-my-birthday".