Day Of Week And Days In Month Example

lua-users home
wiki

The following code provides date functions that include calculating the number of days in a given month and the day of week for a given calendar day.

-- returns the number of days in a given month and year

-- Compatible with Lua 5.0 and 5.1.

-- from sam_lie 

function get_days_in_month(month, year)

  local days_in_month = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }   

  local d = days_in_month[month]

   

  -- check for leap year

  if (month == 2) then

    if (math.mod(year,4) == 0) then

     if (math.mod(year,100) == 0)then                

      if (math.mod(year,400) == 0) then                    

          d = 29

      end

     else                

      d = 29

     end

    end

  end



  return d  

end



-- RiciLake comments:

-- It would be better to create the days_in_month table outside the

-- function, like this (using % so it only works in Lua 5.1)

do

  local days_in_month = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }



  local function is_leap_year(year)

    return year % 4 == 0 and (year % 100 ~= 0 or year % 400 == 0)

  end



  function get_days_in_month(month, year)

    if month == 2 and is_leap_year(year) then

      return 29

    else

      return days_in_month[month]

    end

  end

end



-- It's also possible to avoid the table altogether:

  function get_days_in_month(month, year)

    return month == 2 and is_leap_year(year) and 29

           or ("\31\28\31\30\31\30\31\31\30\31\30\31"):byte(month)

  end



Alternate version - by RichardWarburton - returns number of days in a given month and year by using built in Lua libs. [*1]

function get_days_in_month(mnth, yr)

  return os.date('*t',os.time{year=yr,month=mnth+1,day=0})['day']

end

-- returns the day of week integer and the name of the week

-- Compatible with Lua 5.0 and 5.1.

-- from sam_lie 

function get_day_of_week(dd, mm, yy) 

  local days = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }



  local mmx = mm



  if (mm == 1) then  mmx = 13; yy = yy-1  end

  if (mm == 2) then  mmx = 14; yy = yy-1  end



  local val8 = dd + (mmx*2) +  math.floor(((mmx+1)*3)/5)   + yy + math.floor(yy/4)  - math.floor(yy/100)  + math.floor(yy/400) + 2

  local val9 = math.floor(val8/7)

  local dw = val8-(val9*7) 



  if (dw == 0) then

    dw = 7

  end



  return dw, days[dw]

end



-- alternate version - returns the day of week integer and the name of the week

-- Compatible with Lua 5.0 and 5.1.

-- from http://richard.warburton.it 

function get_day_of_week(dd, mm, yy)

  dw=os.date('*t',os.time{year=yy,month=mm,day=dd})['wday']

  return dw,({"Sun","Mon","Tue","Wed","Thu","Fri","Sat" })[dw]

end



-- given a string date of '2006-12-31' breaks it down to integer yy, mm and dd

-- Compatible with Lua 5.0 and 5.1.

-- from sam_lie 

function get_date_parts(date_str)

  local iyy, imm, idd 



  if (date_str) then

    x = string.gsub(date_str, "(%d+)-(%d+)-(%d+)", function (yy,mm,dd)    

        iyy = tonumber(yy)

        imm = tonumber(mm)

        idd = tonumber(dd)

      end)

  end



  return iyy, imm, idd

end



-- alternate version - given a string date of '2006-12-31' breaks it down to integer yy, mm and dd

-- Compatible with Lua 5.0 and 5.1.

-- from http://richard.warburton.it 

function get_date_parts(date_str)

  _,_,y,m,d=string.find(date_str, "(%d+)-(%d+)-(%d+)")

  return tonumber(y),tonumber(m),tonumber(d)

end



Here is a test suite.

assert(get_days_in_month(1,2007) == 31)

assert(get_days_in_month(2,2007) == 28)

assert(get_days_in_month(3,2007) == 31)

assert(get_days_in_month(4,2007) == 30)

assert(get_days_in_month(5,2007) == 31)

assert(get_days_in_month(6,2007) == 30)

assert(get_days_in_month(7,2007) == 31)

assert(get_days_in_month(8,2007) == 31)

assert(get_days_in_month(9,2007) == 30)

assert(get_days_in_month(10,2007) == 31)

assert(get_days_in_month(11,2007) == 30)

assert(get_days_in_month(12,2007) == 31)

-- See http://en.wikipedia.org/wiki/Leap_year

assert(get_days_in_month(2,2008) == 29) -- leap year

assert(get_days_in_month(2,2000) == 29) -- leap year



-- note: this can fail in Richard's implementation. [*1]

assert(get_days_in_month(2,1900) == 28) -- not leap year



local i, n = get_day_of_week(1,1,2007)

assert(i == 2 and n == 'Mon')

assert(get_day_of_week(1,1,2007) == 2)

assert(get_day_of_week(2,1,2007) == 3)

assert(get_day_of_week(3,1,2007) == 4)

assert(get_day_of_week(4,1,2007) == 5)

assert(get_day_of_week(5,1,2007) == 6)

assert(get_day_of_week(6,1,2007) == 7)

assert(get_day_of_week(7,1,2007) == 1)

assert(get_day_of_week(1,2,2007) == 5)

See also [Wikipedia: Calculating the day of the week]

[*1] LuaList:2007-01/msg00100.html

The following code returns a table containing {year=years, month=months, day=days, hour=hours, min=minutes, sec=seconds} representing the time between two dates created by os.time - by RichardWarburton.

local timeDiff = function(t2,t1)

	local d1,d2,carry,diff = os.date('*t',t1),os.date('*t',t2),false,{}

	local colMax = {60,60,24,os.date('*t',os.time{year=d1.year,month=d1.month+1,day=0}).day,12}

	d2.hour = d2.hour - (d2.isdst and 1 or 0) + (d1.isdst and 1 or 0) -- handle dst

	for i,v in ipairs({'sec','min','hour','day','month','year'}) do 

		diff[v] = d2[v] - d1[v] + (carry and -1 or 0)

		carry = diff[v] < 0

		if carry then diff[v] = diff[v] + colMax[i] end

	end

	return diff

end



local td=timeDiff(os.time{year=2007,month=10,day=5,hour=10,min=10,sec=5},os.time{year=2006,month=11,day=6,hour=10,min=10,sec=5})

for i,v in pairs(td) do print(i,v) end



min     0

day     29

month   10

sec     0

hour    1

year    0


RecentChanges · preferences
edit · history
Last edited April 24, 2007 12:44 pm GMT (diff)