Кризисный 2020 год прошел незаметно
Я не знаю, помнишь ли ты еще
В начале года на Weibo долгое время зависал горячий поиск #Restart2020#.
в самые трудные дни
Обычные люди должны меньше смотреть мобильные телефоны и меньше новостей
Для снятия внутренней депрессии и беспокойства
В этом году некоторые люди не несли его
Но в конце концов, больше людей спустилось
На данный момент у нас закончилась новогодняя ночь
Вот и наступил новый 2021 год...
Чувства не сказать
Кхм, интересно, безопасна ли новогодняя ночь?
"ГГГГ-ММ-дд" Новогодние яйца вам не прислали?
моделирование аварии
Увидев результаты работы вышеуказанной программы, у всех обязательно возникнут сомнения, ведь Мао другой (шепчет про себя: "Нет, раньше проблем не было")
анализ аварий
Поскольку есть сомнения, давайте просмотрим Java Api, найдем документ в Интернете и найдемSimpleDateFormatВ нем есть описание формата даты, помогу найти:Онлайн-ссылка Java API
Внутри АпиyИнтерпретацияyear, хорошо поняли смысл года, тоYИнтерпретацияWeek year, представляет год, в котором находится эта неделя, и поскольку эта неделя приходится на канун Нового года, то эта неделя засчитывается в следующий год, поэтому появилась показанная выше сцена аварии.
Неделя в чужой стране начинается в воскресенье и заканчивается в субботу, на самом деле эта проблема уже возникла 27 декабря 2020 г. Если приведенный выше тестовый код изменить на 27, он также станет 27 декабря 2021 г.
В проекте следует стараться не прописывать формат вручную каждый раз при конвертации даты, здесь неизбежно возникнут такие проблемы, и единое определениеDateUtilкласс, который предоставляет различные методы преобразования форматов и постоянные определения часто используемых форматов, так что пасхалки в Новом году будут заменены, ха-ха
public class DateUtil{
/**
* 日期格式,年份,例如:2004,2008
*/
public static final String DATE_FORMAT_YYYY = "yyyy";
/**
* 日期格式,年份和月份,例如:200707,200808
*/
public static final String DATE_FORMAT_YYYYMM = "yyyyMM";
/**
* 日期格式,年份和月份,例如:200707,2008-08
*/
public static final String DATE_FORMAT_YYYY_MM = "yyyy-MM";
/**
* 日期格式,年月日,例如:050630,080808
*/
public static final String DATE_FORMAT_YYMMDD = "yyMMdd";
/**
* 日期格式,年月日,用横杠分开,例如:06-12-25,08-08-08
*/
public static final String DATE_FORMAT_YY_MM_DD = "yy-MM-dd";
/**
* 日期格式,年月日,例如:20050630,20080808
*/
public static final String DATE_FORMAT_YYYYMMDD = "yyyyMMdd";
/**
* 日期格式,年月日,用横杠分开,例如:2006-12-25,2008-08-08
*/
public static final String DATE_FORMAT_YYYY_MM_DD = "yyyy-MM-dd";
/**
* 日期格式,年月日,例如:2016.10.05
*/
public static final String DATE_FORMAT_POINTYYYYMMDD = "yyyy.MM.dd";
/**
* 日期格式,年月日,例如:2016年10月05日
*/
public static final String DATE_TIME_FORMAT_YYYY年MM月DD日 = "yyyy年MM月dd日";
/**
* 日期格式,年月日时分,例如:200506301210,200808081210
*/
public static final String DATE_FORMAT_YYYYMMDDHHmm = "yyyyMMddHHmm";
/**
* 日期格式,年月日时分,例如:20001230 12:00,20080808 20:08
*/
public static final String DATE_TIME_FORMAT_YYYYMMDD_HH_MI = "yyyyMMdd HH:mm";
/**
* 日期格式,年月日时分,例如:2000-12-30 12:00,2008-08-08 20:08
*/
public static final String DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI = "yyyy-MM-dd HH:mm";
/**
* 日期格式,年月日时分秒,例如:20001230120000,20080808200808
*/
public static final String DATE_TIME_FORMAT_YYYYMMDDHHMISS = "yyyyMMddHHmmss";
/**
* 日期格式,年月日时分秒,年月日用横杠分开,时分秒用冒号分开
* 例如:2005-05-10 23:20:00,2008-08-08 20:08:08
*/
public static final String DATE_TIME_FORMAT_YYYY_MM_DD_HH_MI_SS = "yyyy-MM-dd HH:mm:ss";
/**
* 日期格式,年月日时分秒毫秒,例如:20001230120000123,20080808200808456
*/
public static final String DATE_TIME_FORMAT_YYYYMMDDHHMISSSSS = "yyyyMMddHHmmssSSS";
/**
* 日期格式,月日时分,例如:10-05 12:00
*/
public static final String DATE_FORMAT_MMDDHHMI = "MM-dd HH:mm";
}
Пополнить
Кроме того,SimpleDateFormatЭто не потокобезопасно и не рекомендуется.При высоком уровне параллелизма могут возникать проблемы.Как это решить?
-
Как использовать локальные переменные
public class DateUtil{ public static String formatDate(Date date)throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.format(date); } public static Date parse(String strDate) throws ParseException { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return sdf.parse(strDate); } }использовать при необходимости
SimpleDateFormatСоздайте новый экземпляр в том месте, где можно избежать проблемы многопоточности всякий раз, когда объект с проблемой безопасности потоков изменяется с общего на локальный частный, но это также увеличивает нагрузку на создание объектов. В целом на производительность это особо не влияет. -
Плюс генлок
public class DateUtil { private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public static String formatDate(Date date)throws ParseException { synchronized (sdf){ return sdf.format(date); } } public static Date parse(String strDate) throws ParseException{ synchronized (sdf){ return sdf.parse(strDate); } } }Таким образом, когда поток вызывает, другие потоки, которые хотят вызвать этот метод, должны блокироваться, и когда многопоточный параллелизм велик, это будет иметь определенное влияние на производительность.
-
использовать
ThreadLocalpublic class DateUtil { private static ThreadLocal<DateFormat> sdfThreadLocal = new ThreadLocal<DateFormat>(){ @Override public SimpleDateFormat initialValue(){ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); } }; public static String formatDate(Date date)throws ParseException { return sdfThreadLocal.get().format(date); } public static Date parse(String strDate) throws ParseException{ return sdfThreadLocal.get().parse(strDate); } }использовать
ThreadLocal, Это также превращает общие переменные в монопольное использование.Эксклюзивное использование потоков может определенно уменьшить накладные расходы на создание объектов в параллельной среде, чем монопольное использование методов. -
использовать
DateTimeFormatterDateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); //字符串转日期 LocalDate localDate = LocalDate.parse("2021-01-01 21:50:50",formatter); //日期转字符串 LocalTime localTime = LocalTime.now(); String strLocalTime = localTime.format(formatter); //yyyyMMdd String strLocalTime1 = localTime.format(DateTimeFormatter.BASIC_ISO_DATE);Приведенный выше код является просто примером, о
DateTimeFormatterЕсть также много удобных применений, он предоставляет несколько встроенных форматов, поэтому вам не нужно писать его самостоятельно. а такжеSimpleDateFormatразница в том,DateTimeFormatterЭто не только неизменяемый объект, но и потокобезопасный.DateTimeFormatterВы можете просто создать один экземпляр и ссылаться на него везде.
Желаю вам всего наилучшего в 2021 году и скорейшего окончания эпидемии!
Если у вас есть какие-либо вопросы, пожалуйста, обратите внимание на публичный аккаунт [Hugh's Whiteboard] Пишите мне в личку, обсуждайте и учитесь вместе